pub trait Diff: Sized {
type Delta: Clone + Serialize + DeserializeOwned + Send + Sync;
// Required methods
fn diff(old: &Self, new: &Self) -> Self::Delta;
fn apply(base: &Self, delta: &Self::Delta) -> Self;
}delta-checkpoint and graph only.Expand description
Trait for types that can compute and apply incremental diffs.
Implementors define an associated Delta type representing the difference
between two instances. The trait guarantees a round-trip property:
For any states
s1ands2,Diff::apply(&s1, &Diff::diff(&s1, &s2)) == s2.
§Example
use adk_graph::delta::Diff;
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, PartialEq)]
struct Counter(u64);
#[derive(Clone, Debug, Serialize, Deserialize)]
struct CounterDelta(i64);
impl Diff for Counter {
type Delta = CounterDelta;
fn diff(old: &Self, new: &Self) -> Self::Delta {
CounterDelta(new.0 as i64 - old.0 as i64)
}
fn apply(base: &Self, delta: &Self::Delta) -> Self {
Counter((base.0 as i64 + delta.0) as u64)
}
}
let s1 = Counter(5);
let s2 = Counter(12);
let delta = Counter::diff(&s1, &s2);
assert_eq!(Counter::apply(&s1, &delta), s2);Required Associated Types§
Required Methods§
Sourcefn diff(old: &Self, new: &Self) -> Self::Delta
fn diff(old: &Self, new: &Self) -> Self::Delta
Compute the delta that transforms old into new.
The returned delta, when applied to old via Diff::apply, must
reproduce new exactly.
Sourcefn apply(base: &Self, delta: &Self::Delta) -> Self
fn apply(base: &Self, delta: &Self::Delta) -> Self
Apply a delta to a base state, producing the resulting state.
This is the inverse of Diff::diff: applying the delta produced by
diff(old, new) to old yields new.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl Diff for HashMap<String, Value>
impl Diff for HashMap<String, Value>
Source§fn diff(
old: &HashMap<String, Value>,
new: &HashMap<String, Value>,
) -> <HashMap<String, Value> as Diff>::Delta
fn diff( old: &HashMap<String, Value>, new: &HashMap<String, Value>, ) -> <HashMap<String, Value> as Diff>::Delta
Compute the delta between two HashMap<String, Value> instances.
Classifies each key into one of three categories:
- added: present in
newbut absent fromold - removed: present in
oldbut absent fromnew - modified: present in both but with different values
§Example
use adk_graph::delta::Diff;
use serde_json::{Value, json};
use std::collections::HashMap;
let old: HashMap<String, Value> = [
("x".to_string(), json!("hello")),
("y".to_string(), json!(42)),
].into_iter().collect();
let new: HashMap<String, Value> = [
("x".to_string(), json!("world")),
("z".to_string(), json!(true)),
].into_iter().collect();
let delta = <HashMap<String, Value> as Diff>::diff(&old, &new);
assert!(delta.added.contains_key("z"));
assert!(delta.removed.contains(&"y".to_string()));
assert!(delta.modified.contains_key("x"));Source§fn apply(
base: &HashMap<String, Value>,
delta: &<HashMap<String, Value> as Diff>::Delta,
) -> HashMap<String, Value>
fn apply( base: &HashMap<String, Value>, delta: &<HashMap<String, Value> as Diff>::Delta, ) -> HashMap<String, Value>
Apply a delta to a base HashMap<String, Value>, producing the resulting map.
Operations are applied in order: remove keys, insert added keys, update modified keys.
§Example
use adk_graph::delta::Diff;
use serde_json::{Value, json};
use std::collections::HashMap;
let old: HashMap<String, Value> = [
("a".to_string(), json!(1)),
("b".to_string(), json!(2)),
].into_iter().collect();
let new: HashMap<String, Value> = [
("a".to_string(), json!(1)),
("c".to_string(), json!(3)),
].into_iter().collect();
let delta = <HashMap<String, Value> as Diff>::diff(&old, &new);
assert_eq!(<HashMap<String, Value> as Diff>::apply(&old, &delta), new);type Delta = MapDelta
Source§impl Diff for String
impl Diff for String
Source§fn diff(old: &String, new: &String) -> <String as Diff>::Delta
fn diff(old: &String, new: &String) -> <String as Diff>::Delta
Compute the delta between two strings using character-level diffing.
Uses similar::TextDiff::from_chars() to compute the minimal set of
edit operations that transform old into new.
§Example
use adk_graph::delta::{Diff, StringOp};
let old = "abcdef".to_string();
let new = "abXYef".to_string();
let delta = <String as Diff>::diff(&old, &new);
// The delta contains: Equal("ab"), Delete(2), Insert("XY"), Equal("ef")
assert_eq!(<String as Diff>::apply(&old, &delta), new);Source§fn apply(base: &String, delta: &<String as Diff>::Delta) -> String
fn apply(base: &String, delta: &<String as Diff>::Delta) -> String
Apply a delta to a base string, producing the resulting string.
Replays the edit operations in order:
Equal(s): advance pasts.len()characters in the base (copy them)Delete(n): skipncharacters in the baseInsert(s): appendsto the result
§Example
use adk_graph::delta::Diff;
let old = "hello world".to_string();
let new = "hello rust".to_string();
let delta = <String as Diff>::diff(&old, &new);
assert_eq!(<String as Diff>::apply(&old, &delta), new);type Delta = StringDelta
Source§impl Diff for Vec<Value>
impl Diff for Vec<Value>
Source§fn diff(old: &Vec<Value>, new: &Vec<Value>) -> <Vec<Value> as Diff>::Delta ⓘ
fn diff(old: &Vec<Value>, new: &Vec<Value>) -> <Vec<Value> as Diff>::Delta ⓘ
Compute the delta between two Vec<Value> instances.
If new is a strict extension of old (i.e., old is a prefix of new),
the delta captures only the appended items and the start index. Otherwise,
the delta stores the full new vec as a replacement.
§Example
use adk_graph::delta::Diff;
use serde_json::{Value, json};
// Append case
let old = vec![json!("a"), json!("b")];
let new = vec![json!("a"), json!("b"), json!("c")];
let delta = <Vec<Value> as Diff>::diff(&old, &new);
assert!(!delta.full_replacement);
// Modification case (full replacement)
let old = vec![json!(1), json!(2)];
let new = vec![json!(1), json!(99)];
let delta = <Vec<Value> as Diff>::diff(&old, &new);
assert!(delta.full_replacement);Source§fn apply(base: &Vec<Value>, delta: &<Vec<Value> as Diff>::Delta) -> Vec<Value>
fn apply(base: &Vec<Value>, delta: &<Vec<Value> as Diff>::Delta) -> Vec<Value>
Apply a delta to a base Vec<Value>, producing the resulting vec.
If the delta is a full replacement, the base is ignored and the delta’s
items are returned directly. Otherwise, the base is truncated to
start_index and the delta’s items are appended.
§Example
use adk_graph::delta::Diff;
use serde_json::{Value, json};
let old = vec![json!(1), json!(2)];
let new = vec![json!(1), json!(2), json!(3)];
let delta = <Vec<Value> as Diff>::diff(&old, &new);
assert_eq!(<Vec<Value> as Diff>::apply(&old, &delta), new);