# hashmark Project Guide
## Project Overview
hashmark is a Rust library for efficient change detection using Merkle tree hashing. It combines:
- **Serde** for tree construction and field name tracking
- **bevy_reflect** for runtime field reference access
## Quick Commands
```bash
just build # Build the project
just test # Run all tests
just lint # Run clippy
just format # Format code
just check # Run format-check, lint, and test
just example simple # Run the simple example
just example reflect # Run the reflect example
```
## Architecture
```
src/
├── lib.rs # Public exports and crate docs
├── serializer.rs # Serde Serializer that builds Merkle trees
├── merkle.rs # Merkle tree types (Node, Digest, etc.)
├── diff.rs # Diff algorithm (merkle_diff)
├── path.rs # FieldPath for tracking change locations
├── reflect.rs # bevy_reflect integration (diff_reflect)
└── error.rs # Error types
examples/
├── simple.rs # Basic usage with merkle_diff
├── reflect.rs # Advanced usage with diff_reflect
└── remote_sync.rs # Distributed sync with Merkle trees
```
## Key Types
- `Merkle` - A node in the Merkle tree with digest and structure
- `Node` - Enum: Leaf, Struct, Seq, Enum, Map, Unit, None
- `FieldPath` - Path to a field (e.g., "address.city")
- `Diff` - Result of comparison: Same or Different(DiffDetail)
- `ReflectedChange` - Change with actual field references
## Two API Levels
### Level 1: Path-based (Serialize only)
```rust
let m1 = tree_hash(&old)?;
let m2 = tree_hash(&new)?;
let diff = merkle_diff(&m1, &m2);
```
### Level 2: With references (Serialize + Reflect)
```rust
let changes = diff_reflect(&old, &new)?;
// changes[0].old: Option<&dyn PartialReflect>
```
## Testing
Tests are in each module's `#[cfg(test)]` block. Run with:
```bash
cargo test
```
Doc tests validate examples in documentation.
## Documentation
- `docs/DESIGN.md` - Architecture and design decisions
- `docs/FEATURES.md` - Feature overview and usage
- `docs/ROADMAP.md` - Implementation phases and future work
## Common Patterns
### Adding a new Node type
1. Add variant to `Node` enum in `merkle.rs`
2. Handle in `TreeHashSerializer` in `serializer.rs`
3. Handle in `merkle_diff` in `diff.rs`
4. Handle in `DiffDetail::collect_paths` in `diff.rs`
### Adding path segment types
1. Add variant to `PathSegment` in `path.rs`
2. Update `Display` impl for human-readable output
3. Update `to_reflect_path()` for bevy_reflect compatibility
## Dependencies
- `serde` - Serialization framework
- `bevy_reflect` - Runtime reflection
- `thiserror` - Error derive macro
## Notes
- Types need `#[derive(Serialize)]` for tree hashing
- Types need `#[derive(Serialize, Reflect)]` for `diff_reflect`
- bevy_reflect path format: `.field[0].nested` (leading dot required)
- Map key access via reflection has limitations