1 unstable release
| new 0.1.0 | Jan 13, 2026 |
|---|
#4 in #change-detection
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