You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/docs/specta/rfc/flightscience.mdx
+95Lines changed: 95 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1808,6 +1808,101 @@ I have some concerns about this approach with [rspc](https://github.com/specta-r
1808
1808
1809
1809
### BigInt and special-float support in Tauri
1810
1810
1811
+
BigInt's have a different constraint, there JSON representation is lossly. Mainly:
1812
+
- When `JSON.parse` is run large integers are truncated.
1813
+
- `NaN`, `Infinity` and `-Infinity` all become `null`
1814
+
1815
+
So at it's core, doing `commandResult.then((v) => BigInt(v))` will still result in truncation if `v` is a `number`. So you need a way of serializing these correctly in Rust.
1816
+
1817
+
#### Jsone
1818
+
1819
+
[Jsone](https://github.com/specta-rs/jsone) is a new crate I built out of my work looking at solutions here.
1820
+
1821
+
At it's core it's one simple API: `pub struct Jsone<T>(pub T);`
1822
+
1823
+
However internally it wraps the `Serializer` and `Deserializer` with it's own as it passes through the `Serialize for Jsone<T>` and `Deserialize for Jsone<T>` implementations.
1824
+
1825
+
Using Serde methods we can capture large numbers, `NaN`, `Infinity` and `-Infinity` and encode them in a lossless way.
1826
+
1827
+
Below is the example from the repository which shows it pretty clearly:
let payload: Jsone<Payload<f64>> = serde_json::from_str(&json).unwrap();
1872
+
assert!(payload.0.id.is_nan());
1873
+
println!("{payload:?}");
1874
+
}
1875
+
}
1876
+
```
1877
+
1878
+
Main things to note:
1879
+
- large numbers become `{"$$jsone$remap$$": "{number}" }` in JSON
1880
+
- Stringifying preserves it through `JSON.parse`.
1881
+
- The JS runtime will do `BigInt({number})` automatically so you effectively get `number | bigint` for all fields.
1882
+
- float special cases become `{"$$jsone$remap$$": {constant} }` where constant is:
1883
+
- `1` for `NaN`
1884
+
- `2` for `Infinity`
1885
+
- `3` for `-Infinity`
1886
+
1887
+
This requires both the Rust wrapper on serialization and deserialization and a small utility in JS to run within the `reviver`/`replacer` param for `JSON.parse`/`JSON.stringify` (although it can be used later).
1888
+
1889
+
This makes the transport layer lossless. Now we need the Specta integration, this is done using `specta_typescript::semantic`.
0 commit comments