MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / diff_strings

Function diff_strings

nodedb/src/event/field_diff.rs:284–343  ·  view source on GitHub ↗

Diff two strings, producing TextInsert/TextDelete for simple edits or Modified for complex changes. Finds the longest common prefix and suffix, then examines the middle. If only text was inserted (old middle is empty), emits TextInsert. If only text was deleted (new middle is empty), emits TextDelete. Otherwise, falls back to Modified.

(diffs: &mut Vec<FieldDiff>, prefix: &str, old_s: &str, new_s: &str)

Source from the content-addressed store, hash-verified

282/// If only text was deleted (new middle is empty), emits TextDelete.
283/// Otherwise, falls back to Modified.
284fn diff_strings(diffs: &mut Vec<FieldDiff>, prefix: &str, old_s: &str, new_s: &str) {
285 let old_chars: Vec<char> = old_s.chars().collect();
286 let new_chars: Vec<char> = new_s.chars().collect();
287
288 // Common prefix length.
289 let common_prefix = old_chars
290 .iter()
291 .zip(new_chars.iter())
292 .take_while(|(a, b)| a == b)
293 .count();
294
295 // Common suffix length (from the end, not overlapping with prefix).
296 let old_remaining = old_chars.len() - common_prefix;
297 let new_remaining = new_chars.len() - common_prefix;
298 let common_suffix = old_chars[common_prefix..]
299 .iter()
300 .rev()
301 .zip(new_chars[common_prefix..].iter().rev())
302 .take_while(|(a, b)| a == b)
303 .count();
304
305 let old_mid_len = old_remaining - common_suffix;
306 let new_mid_len = new_remaining - common_suffix;
307
308 if old_mid_len == 0 && new_mid_len > 0 {
309 // Pure insertion.
310 let inserted: String = new_chars[common_prefix..common_prefix + new_mid_len]
311 .iter()
312 .collect();
313 diffs.push(FieldDiff {
314 field: prefix.to_owned(),
315 op: DiffOp::TextInsert,
316 old_value: Some(serde_json::Value::Number(serde_json::Number::from(
317 common_prefix,
318 ))),
319 new_value: Some(serde_json::Value::String(inserted)),
320 });
321 } else if new_mid_len == 0 && old_mid_len > 0 {
322 // Pure deletion.
323 let deleted: String = old_chars[common_prefix..common_prefix + old_mid_len]
324 .iter()
325 .collect();
326 diffs.push(FieldDiff {
327 field: prefix.to_owned(),
328 op: DiffOp::TextDelete,
329 old_value: Some(serde_json::Value::String(deleted)),
330 new_value: Some(serde_json::Value::Number(serde_json::Number::from(
331 common_prefix,
332 ))),
333 });
334 } else {
335 // Replacement or complex change — fall back to Modified.
336 diffs.push(FieldDiff {
337 field: prefix.to_owned(),
338 op: DiffOp::Modified,
339 old_value: Some(serde_json::Value::String(old_s.to_owned())),
340 new_value: Some(serde_json::Value::String(new_s.to_owned())),
341 });

Callers 1

diff_valuesFunction · 0.85

Calls 5

collectMethod · 0.80
countMethod · 0.45
iterMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected