From c9c2b775a815dba32d035fcfcef3030a6d3305b8 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sun, 16 Nov 2025 15:01:51 +0000 Subject: [PATCH] Don't unwrap to MAX number --- src/operation_transformation/edited_text.rs | 62 +++++++++++---------- src/utils/myers_diff.rs | 19 +++---- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/operation_transformation/edited_text.rs b/src/operation_transformation/edited_text.rs index b8059f9..6b65a68 100644 --- a/src/operation_transformation/edited_text.rs +++ b/src/operation_transformation/edited_text.rs @@ -168,13 +168,14 @@ where let result = operation.merge_operations(&mut last_other_op); if let ref op @ (Operation::Insert { .. } | Operation::Equal { .. }) = result { - 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 merged_length_signed = isize::try_from(merged_length) + .expect("merged_length must fit in isize"); + let seen_left_length_signed = isize::try_from(seen_left_length) + .expect("seen_left_length must fit in isize"); + let op_len_signed = + isize::try_from(op.len()).expect("op.len() must fit in isize"); + let original_length_signed = isize::try_from(original_length) + .expect("original_length must fit in isize"); let shift = merged_length_signed - seen_left_length_signed + op_len_signed - original_length_signed; @@ -201,13 +202,14 @@ where let result = operation.merge_operations(&mut last_other_op); if let ref op @ (Operation::Insert { .. } | Operation::Equal { .. }) = result { - 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 merged_length_signed = isize::try_from(merged_length) + .expect("merged_length must fit in isize"); + let seen_right_length_signed = isize::try_from(seen_right_length) + .expect("seen_right_length must fit in isize"); + let op_len_signed = + isize::try_from(op.len()).expect("op.len() must fit in isize"); + let original_length_signed = isize::try_from(original_length) + .expect("original_length must fit in isize"); let shift = merged_length_signed - seen_right_length_signed + op_len_signed - original_length_signed; @@ -355,7 +357,7 @@ where /// Inserts are represented as strings, deletes as negative integers, /// and equal spans as positive integers. #[must_use] - pub fn to_changes(&self) -> Vec { + pub fn to_diff(&self) -> Vec { let mut result: Vec = Vec::with_capacity(self.operations.len()); let mut previous_equal: Option = None; @@ -372,7 +374,7 @@ where Operation::Insert { text, .. } => { if let Some(prev_length) = previous_equal { result.push(NumberOrString::Number( - i64::try_from(prev_length).unwrap_or(i64::MAX), + i64::try_from(prev_length).expect("prev_length must fit in i64"), )); previous_equal = None; } @@ -390,12 +392,13 @@ where } => { if let Some(prev_length) = previous_equal { result.push(NumberOrString::Number( - i64::try_from(prev_length).unwrap_or(i64::MAX), + i64::try_from(prev_length).expect("prev_length must fit in i64"), )); previous_equal = None; } - let count = i64::try_from(*deleted_character_count).unwrap_or(i64::MAX); + let count = i64::try_from(*deleted_character_count) + .expect("deleted_character_count must fit in i64"); result.push(NumberOrString::Number(-count)); } } @@ -403,7 +406,7 @@ where if let Some(prev_length) = previous_equal { result.push(NumberOrString::Number( - i64::try_from(prev_length).unwrap_or(i64::MAX), + i64::try_from(prev_length).expect("prev_length must fit in i64"), )); } @@ -412,19 +415,19 @@ where /// Deserialize an `EditedText` from a change list and the original text. #[must_use] - pub fn from_changes( + pub fn from_diff( original_text: &'a str, - simple_operations: Vec, + diff: Vec, tokenizer: &Tokenizer, ) -> EditedText<'a, T> { - let mut operations: Vec> = Vec::with_capacity(simple_operations.len()); + let mut operations: Vec> = Vec::with_capacity(diff.len()); let mut order = 0; - for simple_operation in simple_operations { - match simple_operation { + for item in diff { + match item { NumberOrString::Number(length) => { if length >= 0 { - let length = usize::try_from(length).unwrap_or(usize::MAX); + let length = usize::try_from(length).expect("length must fit in usize"); let original_characters: String = original_text.chars().skip(order).take(length).collect(); @@ -435,7 +438,8 @@ where order += token.get_original_length(); } } else { - let length = usize::try_from(-length).unwrap_or(usize::MAX); + let length = + usize::try_from(-length).expect("negative length must fit in usize"); operations.push(Operation::create_delete(order, length)); order += length; } @@ -509,7 +513,7 @@ mod tests { let original = "Merging text is hard!"; let changes = "Merging text is easy with reconcile!"; let result = EditedText::from_strings(original, &changes.into()); - let serialized = serde_yaml::to_string(&result.to_changes()).unwrap(); + let serialized = serde_yaml::to_string(&result.to_diff()).unwrap(); let expected = concat!("- 15\n", "- -6\n", "- ' easy with reconcile!'\n",); assert_eq!(serialized, expected); @@ -523,9 +527,9 @@ mod tests { let edited_text = EditedText::from_strings(original, &updated.into()); - let changes = edited_text.to_changes(); + let changes = edited_text.to_diff(); let deserialized_edited_text = - EditedText::from_changes(original, changes, &*BuiltinTokenizer::Word); + EditedText::from_diff(original, changes, &*BuiltinTokenizer::Word); assert_eq!(deserialized_edited_text.apply().text(), updated); } diff --git a/src/utils/myers_diff.rs b/src/utils/myers_diff.rs index 776e448..df2239a 100644 --- a/src/utils/myers_diff.rs +++ b/src/utils/myers_diff.rs @@ -87,7 +87,7 @@ 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); + let offset = isize::try_from(max_d).expect("max_d must fit in isize"); Self { offset, v: vec![0; 2 * max_d], @@ -101,16 +101,15 @@ impl Index for V { type Output = 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))] + let idx = usize::try_from(index + self.offset).expect("index + offset must fit in usize"); + &self.v[idx] } } impl IndexMut for V { fn index_mut(&mut self, index: isize) -> &mut Self::Output { - 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))] + let idx = usize::try_from(index + self.offset).expect("index + offset must fit in usize"); + &mut self.v[idx] } } @@ -145,7 +144,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 = isize::try_from(n).unwrap_or(isize::MAX) - isize::try_from(m).unwrap_or(isize::MAX); + let delta = isize::try_from(n).expect("n must fit in isize") - isize::try_from(m).expect("m must fit in isize"); let odd = delta & 1 == 1; // The initial point at (0, -1) @@ -157,7 +156,7 @@ where assert!(vf.len() >= d_max); assert!(vb.len() >= d_max); - let d_max_isize = isize::try_from(d_max).unwrap_or(isize::MAX); + let d_max_isize = isize::try_from(d_max).expect("d_max must fit in isize"); for d in 0..d_max_isize { // Forward path for k in (-d..=d).rev().step_by(2) { @@ -166,7 +165,7 @@ where } else { vf[k - 1] + 1 }; - let y = usize::try_from(isize::try_from(x).unwrap_or(isize::MAX) - k).unwrap_or(0); + let y = usize::try_from(isize::try_from(x).expect("x must fit in isize") - k).expect("x - k must be non-negative and fit in usize"); // The coordinate of the start of a snake let (x0, y0) = (x, y); @@ -204,7 +203,7 @@ where } else { vb[k - 1] + 1 }; - let mut y = usize::try_from(isize::try_from(x).unwrap_or(isize::MAX) - k).unwrap_or(0); + let mut y = usize::try_from(isize::try_from(x).expect("x must fit in isize") - k).expect("x - k must be non-negative and fit in usize"); // The coordinate of the start of a snake if x < n && y < m {