|
| 1 | +# flatted (Rust) |
| 2 | + |
| 3 | +A super light and fast circular JSON parser. |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +```toml |
| 8 | +[dependencies] |
| 9 | +flatted = { path = "../rust" } # or publish path / git dependency |
| 10 | +``` |
| 11 | + |
| 12 | +```rust |
| 13 | +use std::cell::RefCell; |
| 14 | +use std::rc::Rc; |
| 15 | + |
| 16 | +use flatted::{parse_simple, stringify_simple, Object, Value}; |
| 17 | + |
| 18 | +fn main() { |
| 19 | + // const a = [{}]; a[0].a = a; a.push(a); |
| 20 | + let a = Value::Array(Rc::new(RefCell::new(vec![Value::empty_object()]))); |
| 21 | + let first = a.as_array().unwrap().borrow()[0].clone(); |
| 22 | + first |
| 23 | + .as_object() |
| 24 | + .unwrap() |
| 25 | + .borrow_mut() |
| 26 | + .insert("a".into(), a.clone()); |
| 27 | + a.as_array().unwrap().borrow_mut().push(a.clone()); |
| 28 | + |
| 29 | + let s = stringify_simple(&a).unwrap(); |
| 30 | + assert_eq!(s, r#"[["1","0"],{"a":"0"}]"#); |
| 31 | + |
| 32 | + let back = parse_simple(&s).unwrap(); |
| 33 | + let again = back.as_array().unwrap().borrow()[1].clone(); |
| 34 | + let self_ref = again.as_object().unwrap().borrow().get("a").cloned().unwrap(); |
| 35 | + assert!(back.ptr_eq(&self_ref)); |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +Arrays and objects use `Rc<RefCell<_>>` so circular and shared references keep |
| 40 | +their identity after parsing (Rust has no built-in reference-typed JSON value). |
| 41 | + |
| 42 | +## API |
| 43 | + |
| 44 | +| Function | Role | |
| 45 | +|----------|------| |
| 46 | +| `stringify(value, replacer, space)` | Flatten to flatted JSON text | |
| 47 | +| `parse(text, reviver)` | Restore a recursive value graph | |
| 48 | +| `to_json(value)` | Flatten to a plain `serde_json::Value` array | |
| 49 | +| `from_json(value)` | Restore recursion from that array | |
| 50 | +| `stringify_simple` / `parse_simple` | Same without replacer/reviver/space | |
| 51 | + |
| 52 | +## CLI |
| 53 | + |
| 54 | +```bash |
| 55 | +cargo build --release --features cli |
| 56 | +echo '{"a":"b"}' | ./target/release/flatted |
| 57 | +echo '[{"a":"1"},"b"]' | ./target/release/flatted -d |
| 58 | +``` |
| 59 | + |
| 60 | +## Test |
| 61 | + |
| 62 | +```bash |
| 63 | +cargo test |
| 64 | +``` |
| 65 | + |
| 66 | +## Bench (vs JS) |
| 67 | + |
| 68 | +Same 1s wall-clock methodology as `test/bench.js`: |
| 69 | + |
| 70 | +```bash |
| 71 | +# from repo root — compares ESM/JS vs Rust release |
| 72 | +npm run bench:js-rs |
| 73 | + |
| 74 | +# or individually |
| 75 | +node test/bench-flatted.mjs |
| 76 | +cargo run --example bench --release --manifest-path rust/Cargo.toml |
| 77 | +``` |
| 78 | + |
| 79 | +## Note on crates.io |
| 80 | + |
| 81 | +The name `flatted` is already taken on crates.io by an unofficial port. This |
| 82 | +directory is the official WebReflection port in this repository; publish naming |
| 83 | +can be decided separately (for example a scoped / renamed crate). |
0 commit comments