From 7d242e199916594cf2af58f2e5f2779423268b4b Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sat, 5 Jul 2025 10:13:11 +0100 Subject: [PATCH] Enable cast lints --- Cargo.toml | 5 --- src/operation_transformation/edited_text.rs | 38 +++++++++++++++------ src/operation_transformation/operation.rs | 21 ++++-------- src/utils/myers_diff.rs | 22 ++++++++---- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9adae81..da7375a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,11 +80,6 @@ verbose_file_reads = "warn" large_stack_arrays = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/13774 -# TODO: fix these -cast_possible_truncation = { level = "allow", priority = 1 } -cast_sign_loss = { level = "allow", priority = 1 } -cast_possible_wrap = { level = "allow", priority = 1 } - # Silly lints implicit_return = { level = "allow", priority = 1 } question_mark_used = { level = "allow", priority = 1 } diff --git a/src/operation_transformation/edited_text.rs b/src/operation_transformation/edited_text.rs index 7b7421a..5edfe03 100644 --- a/src/operation_transformation/edited_text.rs +++ b/src/operation_transformation/edited_text.rs @@ -144,18 +144,26 @@ where Operation::Insert { .. } | Operation::Equal { .. } ); - let original_length = operation.len() as isize; + let original_length = operation.len(); let result = match side { Side::Left => { let result = operation.merge_operations(&mut last_other_op); if let ref op @ (Operation::Insert { .. } | Operation::Equal { .. }) = result { - let shift = merged_length as isize - seen_left_length as isize - + op.len() as isize - - original_length; + // Calculate shift using safe casts - preserving original logic + let merged_length_signed = + isize::try_from(merged_length).unwrap_or(isize::MAX); + let seen_left_length_signed = + isize::try_from(seen_left_length).unwrap_or(isize::MAX); + let op_len_signed = isize::try_from(op.len()).unwrap_or(isize::MAX); + let original_length_signed = + isize::try_from(original_length).unwrap_or(isize::MAX); + + let shift = merged_length_signed - seen_left_length_signed + op_len_signed + - original_length_signed; while let Some(cursor) = left_cursors.next_if(|cursor| { - cursor.char_index <= seen_left_length + original_length as usize + cursor.char_index <= seen_left_length + original_length }) { merged_cursors.push( cursor.with_index(cursor.char_index.saturating_add_signed(shift)), @@ -164,7 +172,7 @@ where } if is_advancing_operation { - seen_left_length += original_length as usize; + seen_left_length += original_length; } maybe_left_op = left_iter.next(); @@ -176,12 +184,20 @@ where let result = operation.merge_operations(&mut last_other_op); if let ref op @ (Operation::Insert { .. } | Operation::Equal { .. }) = result { - let shift = merged_length as isize - seen_right_length as isize - + op.len() as isize - - original_length; + // Calculate shift using safe casts - preserving original logic + let merged_length_signed = + isize::try_from(merged_length).unwrap_or(isize::MAX); + let seen_right_length_signed = + isize::try_from(seen_right_length).unwrap_or(isize::MAX); + let op_len_signed = isize::try_from(op.len()).unwrap_or(isize::MAX); + let original_length_signed = + isize::try_from(original_length).unwrap_or(isize::MAX); + + let shift = merged_length_signed - seen_right_length_signed + op_len_signed + - original_length_signed; while let Some(cursor) = right_cursors.next_if(|cursor| { - cursor.char_index <= seen_right_length + original_length as usize + cursor.char_index <= seen_right_length + original_length }) { merged_cursors.push( cursor.with_index(cursor.char_index.saturating_add_signed(shift)), @@ -190,7 +206,7 @@ where } if is_advancing_operation { - seen_right_length += original_length as usize; + seen_right_length += original_length; } maybe_right_op = right_iter.next(); diff --git a/src/operation_transformation/operation.rs b/src/operation_transformation/operation.rs index ef0a674..1c3060c 100644 --- a/src/operation_transformation/operation.rs +++ b/src/operation_transformation/operation.rs @@ -241,7 +241,7 @@ where *last_delete_order + *last_delete_deleted_character_count; let new_length = deleted_character_count - .min(0.max(operation_end_index as i64 - last_delete_end_index as i64) as usize); + .min(operation_end_index.saturating_sub(last_delete_end_index)); let overlap = deleted_character_count - new_length; @@ -282,30 +282,21 @@ where let last_delete_end_index = *last_delete_order + *last_delete_deleted_character_count; - let overlap = - 0.max((length as i64).min(last_delete_end_index as i64 - order as i64)); + let overlap = length.min(last_delete_end_index.saturating_sub(order)); #[cfg(debug_assertions)] let updated_equal = text.as_ref().map_or_else( - || { - Operation::create_equal( - order + overlap as usize, - (length as i64 - overlap) as usize, - ) - }, + || Operation::create_equal(order + overlap, length - overlap), |text| { Operation::create_equal_with_text( - order + overlap as usize, - text.chars().skip(overlap as usize).collect::(), + order + overlap, + text.chars().skip(overlap).collect::(), ) }, ); #[cfg(not(debug_assertions))] - let updated_equal = Operation::create_equal( - order + overlap as usize, - (length as i64 - overlap) as usize, - ); + let updated_equal = Operation::create_equal(order + overlap, length - overlap); updated_equal } diff --git a/src/utils/myers_diff.rs b/src/utils/myers_diff.rs index 4215125..c4c64a9 100644 --- a/src/utils/myers_diff.rs +++ b/src/utils/myers_diff.rs @@ -86,8 +86,10 @@ struct V { impl V { fn new(max_d: usize) -> Self { + // max_d should fit in isize for the algorithm to work correctly + let offset = isize::try_from(max_d).unwrap_or(isize::MAX); Self { - offset: max_d as isize, + offset, v: vec![0; 2 * max_d], } } @@ -98,12 +100,17 @@ impl V { impl Index for V { type Output = usize; - fn index(&self, index: isize) -> &Self::Output { &self.v[(index + self.offset) as usize] } + fn index(&self, index: isize) -> &Self::Output { + let idx = usize::try_from(index + self.offset).unwrap_or(usize::MAX); + &self.v[idx.min(self.v.len().saturating_sub(1))] + } } impl IndexMut for V { fn index_mut(&mut self, index: isize) -> &mut Self::Output { - &mut self.v[(index + self.offset) as usize] + let idx = usize::try_from(index + self.offset).unwrap_or(usize::MAX); + let len = self.v.len(); + &mut self.v[idx.min(len.saturating_sub(1))] } } @@ -138,7 +145,7 @@ where // By Lemma 1 in the paper, the optimal edit script length is odd or even as // `delta` is odd or even. - let delta = n as isize - m as isize; + let delta = isize::try_from(n).unwrap_or(isize::MAX) - isize::try_from(m).unwrap_or(isize::MAX); let odd = delta & 1 == 1; // The initial point at (0, -1) @@ -150,7 +157,8 @@ where assert!(vf.len() >= d_max); assert!(vb.len() >= d_max); - for d in 0..d_max as isize { + let d_max_isize = isize::try_from(d_max).unwrap_or(isize::MAX); + for d in 0..d_max_isize { // Forward path for k in (-d..=d).rev().step_by(2) { let mut x = if k == -d || (k != d && vf[k - 1] < vf[k + 1]) { @@ -158,7 +166,7 @@ where } else { vf[k - 1] + 1 }; - let y = (x as isize - k) as usize; + let y = usize::try_from(isize::try_from(x).unwrap_or(isize::MAX) - k).unwrap_or(0); // The coordinate of the start of a snake let (x0, y0) = (x, y); @@ -196,7 +204,7 @@ where } else { vb[k - 1] + 1 }; - let mut y = (x as isize - k) as usize; + let mut y = usize::try_from(isize::try_from(x).unwrap_or(isize::MAX) - k).unwrap_or(0); // The coordinate of the start of a snake if x < n && y < m {