Thanks to visit codestin.com
Credit goes to lib.rs

#diff #change-detection #serde

hashmark

Merkle tree hashing for efficient change detection

1 unstable release

new 0.1.0 Jan 13, 2026

#4 in #change-detection

MIT license

71KB
1.5K SLoC

hashmark

Merkle tree hashing for efficient change detection in Rust.

Overview

hashmark builds Merkle trees from your data structures using serde, enabling:

  • Fast change detection via hash comparison
  • Field-level diff paths (e.g., address.city)
  • Field reference access via bevy_reflect
  • Serializable trees for distributed sync

Quick Start

use serde::Serialize;
use hashmark::{tree_hash, merkle_diff, Diff};

#[derive(Serialize)]
struct User {
    name: String,
    age: u32,
}

let old = User { name: "Alice".into(), age: 30 };
let new = User { name: "Alice".into(), age: 31 };

let m1 = tree_hash(&old).unwrap();
let m2 = tree_hash(&new).unwrap();

match merkle_diff(&m1, &m2) {
    Diff::Same => println!("No changes"),
    Diff::Different(detail) => {
        for (path, change) in detail.changed_paths() {
            println!("{}: {:?}", path, change);
        }
    }
}

Remote Sync

Send Merkle trees between peers for efficient distributed sync:

use serde::{Serialize, Deserialize};
use bevy_reflect::Reflect;
use hashmark::{tree_hash, Merkle};

#[derive(Serialize, Deserialize, Reflect)]
struct Config {
    port: u16,
    debug: bool,
}

// Peer A: send merkle tree (not the data)
let config = Config { port: 8080, debug: true };
let merkle = tree_hash(&config).unwrap();
let json = serde_json::to_string(&merkle).unwrap();

// Peer B: receive and compare against local data
let received: Merkle = serde_json::from_str(&json).unwrap();
let local = Config { port: 9000, debug: true };

let changes = received.diff_with_data_reflect(&local).unwrap();
for change in &changes {
    println!("{}: {:?}", change.path, change.change_type);
    // change.local: Option<&dyn PartialReflect>
}

License

MIT

Dependencies

~10–13MB
~172K SLoC