https://github.com/rlch/lorosurgeon
Autosurgeon-style derive macros for Loro CRDT containers
https://github.com/rlch/lorosurgeon
Last synced: 3 months ago
JSON representation
Autosurgeon-style derive macros for Loro CRDT containers
- Host: GitHub
- URL: https://github.com/rlch/lorosurgeon
- Owner: rlch
- License: mit
- Created: 2026-03-10T11:43:53.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-10T14:31:42.000Z (3 months ago)
- Last Synced: 2026-03-10T19:10:01.986Z (3 months ago)
- Language: Rust
- Homepage:
- Size: 113 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# lorosurgeon
[](https://crates.io/crates/lorosurgeon)
[](https://docs.rs/lorosurgeon)
[](https://github.com/rlch/lorosurgeon/actions/workflows/ci.yml)
[](LICENSE)
Derive macros for bidirectional serialization between Rust types and [Loro](https://loro.dev) CRDT containers — the Loro equivalent of [autosurgeon](https://github.com/automerge/autosurgeon) for Automerge.
`#[derive(Hydrate, Reconcile)]` generates field-level mapping between Rust types and Loro containers. Only modified fields produce CRDT operations.
## Quick Start
```rust
use loro::LoroDoc;
use lorosurgeon::{Hydrate, Reconcile, DocSync};
#[derive(Debug, PartialEq, Hydrate, Reconcile)]
#[loro(root = "config")]
struct Config {
name: String,
version: i64,
position: Position,
}
#[derive(Debug, PartialEq, Hydrate, Reconcile)]
struct Position { x: f64, y: f64 }
let doc = LoroDoc::new();
let config = Config {
name: "hello".into(),
version: 1,
position: Position { x: 10.0, y: 20.0 },
};
config.to_doc(&doc).unwrap(); // Rust → Loro
doc.commit();
let loaded = Config::from_doc(&doc).unwrap(); // Loro → Rust
assert_eq!(loaded, config);
```
## Documentation
**[Full API documentation on docs.rs →](https://docs.rs/lorosurgeon)**
The crate docs include type mapping tables, attribute reference, examples for concurrent editing, custom serialization, flatten, keyed list diffing, and more.
## Features
- **Structs** → `LoroMap` (fields become keys)
- **Enums** → `LoroMap` with variant discriminator, unit variants as strings
- **`Vec`** → `LoroList` with Myers LCS diffing
- **`#[loro(movable)]`** → `LoroMovableList` with identity-preserving `mov()`/`set()`
- **`HashMap`** → `LoroMap` with stale-key cleanup
- **`#[loro(text)]`** → `LoroText` with character-level diffing (on `String` fields)
- **No-op detection** — identical values produce zero CRDT operations
- **Concurrent merge** — field-level granularity means independent edits compose
## Attributes
```rust
// Container-level
#[loro(root = "key")] // DocSync: to_doc() / from_doc()
// Field-level
#[key] // Identity key for movable list diffing
#[loro(rename = "name")] // Different key in Loro
#[loro(json)] // serde_json round-trip
#[loro(text)] // LoroText with character-level LCS
#[loro(movable)] // LoroMovableList instead of LoroList
#[loro(default)] // Default::default() when absent
#[loro(default = "fn")] // Custom default function
#[loro(flatten)] // Inline nested struct fields
#[loro(with = "module")] // Custom hydrate + reconcile
#[loro(hydrate = "fn")] // Custom hydrate only
#[loro(reconcile = "fn")] // Custom reconcile only
```
## License
MIT