Skip to content

Commit 0512168

Browse files
committed
Official flatted for rust
1 parent 106735b commit 0512168

15 files changed

Lines changed: 1836 additions & 0 deletions

File tree

.github/workflows/rust.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Rust
2+
3+
on: [push, pull_request]
4+
5+
permissions:
6+
contents: read
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
defaults:
12+
run:
13+
working-directory: ./rust
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v6
18+
19+
- name: Install Rust toolchain
20+
uses: dtolnay/rust-toolchain@stable
21+
with:
22+
components: rustfmt, clippy
23+
24+
- name: Cache cargo
25+
uses: Swatinem/rust-cache@v2
26+
with:
27+
workspaces: rust
28+
29+
- name: Check Formatting
30+
run: cargo fmt --check
31+
32+
- name: Clippy
33+
run: cargo clippy --all-targets -- -D warnings
34+
35+
- name: Test
36+
run: cargo test
37+
38+
- name: Build CLI
39+
run: cargo build --features cli

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ __pycache__
77
# Go artifacts
88
*.test
99
*.out
10+
11+
# Bench fixtures
12+
test/.bench-circular.flatted.json

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Available also for **[Python](./python/flatted.py)**.
1414

1515
Available also for **[Go](./golang/README.md)**.
1616

17+
Available also for **[Rust](./rust/README.md)**.
18+
1719
- - -
1820

1921
## ℹ️ JSON only values

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"test": "c8 node test/index.js",
1616
"test:php": "php php/test.php",
1717
"test:py": "python python/test.py",
18+
"test:rs": "cargo test --manifest-path rust/Cargo.toml",
19+
"bench:js-rs": "node test/bench-js-vs-rs.mjs",
1820
"ts": "tsc -p .",
1921
"coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info"
2022
},
@@ -34,6 +36,7 @@
3436
"php/flatted.php",
3537
"python/flatted.py",
3638
"golang/pkg/flatted/flatted.go",
39+
"rust/src/lib.rs",
3740
"types/"
3841
],
3942
"keywords": [

rust/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
/Cargo.lock
3+
/flatted

rust/Cargo.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[package]
2+
name = "flatted"
3+
version = "0.1.0"
4+
edition = "2021"
5+
rust-version = "1.70"
6+
authors = ["Andrea Giammarchi"]
7+
license = "ISC"
8+
description = "A super light and fast circular JSON parser."
9+
repository = "https://github.com/WebReflection/flatted"
10+
homepage = "https://github.com/WebReflection/flatted"
11+
readme = "README.md"
12+
keywords = ["circular", "json", "parser", "serialize", "flatted"]
13+
categories = ["encoding", "parser-implementations"]
14+
exclude = ["target/"]
15+
16+
[dependencies]
17+
indexmap = "2"
18+
serde_json = { version = "1", default-features = false, features = ["std", "preserve_order"] }
19+
20+
[lib]
21+
name = "flatted"
22+
path = "src/lib.rs"
23+
24+
[[bin]]
25+
name = "flatted"
26+
path = "src/main.rs"
27+
required-features = ["cli"]
28+
29+
[features]
30+
default = []
31+
cli = []

rust/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
BINARY_NAME=flatted
2+
3+
.PHONY: build test lint check clean
4+
5+
build:
6+
cargo build --release --features cli
7+
cp target/release/$(BINARY_NAME) ./$(BINARY_NAME)
8+
9+
test:
10+
cargo test
11+
12+
lint:
13+
cargo fmt --check
14+
cargo clippy --all-targets -- -D warnings
15+
16+
check: test lint
17+
18+
clean:
19+
cargo clean
20+
rm -f $(BINARY_NAME)

rust/README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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

Comments
 (0)