1 unstable release
0.1.0 | Sep 23, 2024 |
---|
#3 in #seq
194 downloads per month
110KB
2.5K
SLoC
Serser – the Rust serialization engine
serser is a serialization/deserialization framework for Rust. It uses a stream of tokens (e.g. U32, Seq, and EndSeq) as the intermediate representation.
Examples
Rust To JSON
use serser::derive::*; // The derive macros.
use serser::json::json_from_tokens;
use serser::prelude::*; // Includes the {From,Into]Tokens traits.
# fn main() -> Result<(), serser::json::WriteError> {
#[derive(FromTokens, IntoTokens)]
struct A {
b: u32
}
let original = A { b: 42 };
let mut json = String::new();
json_from_tokens(&mut json, original)?;
assert_eq!(r#"{"b":42}"#, json);
# Ok(())
# }
JSON To Rust
use serser::derive::*; // The derive macros.
use serser::json::json_into;
use serser::prelude::*; // Includes the {From,Into]Tokens traits.
# fn main() -> Result<(), serser::json::ParseError<serser::TokenError>> {
#[derive(Debug, Eq, PartialEq)] // For the assert_eq.
#[derive(FromTokens, IntoTokens)]
struct A {
b: u32
}
let got = json_into::<A>(r#"{ "b": 42 }"#)?;
assert_eq!(got, A { b: 42 });
# Ok(())
# }
Rust To Rust
This is emulating Clone:
use serser::derive::*; // The derive macros.
use serser::prelude::*; // Includes the {From,Into]Tokens traits.
use serser::TokenVec;
# fn main() -> Result<(), serser::TokenError> {
#[derive(Debug, Eq, PartialEq)] // For the assert_eq.
#[derive(FromTokens, IntoTokens)]
struct A {
b: u32
}
let mut tokens = TokenVec::new(); // A buffer, useful for testing.
let original = A { b: 42 };
original.into_tokens(&mut tokens)?; // Writes to `tokens`.
let clone = A::from_tokens(tokens)?; // Reads from `tokens`.
assert_eq!(clone, original);
# Ok(())
# }
Compared To serde
The serde crate is the defacto standard for serialization, both for JSON and as used in wasm-bindgen for communicating with the host from WebAssembly.
This crate aims to improve on the serde design in these ways:
- A smaller API, making it easier to write custom (de)serializers.
Only one function needs to be implemented for a sink:
yield_token
. Another function can be overridden to provide hints for the next expected token. - A bufferable intermediate representation that can be shared between threads, or stored for later use.
Primarily lightweight, reference-based,
Token
objects are used. AnOwningToken
is provided for easy storage and IPC. - A push-based pipeline, inverting the
Iterator
pattern to allow correct lifetimes to be expressed more easily. Tokens only live during the yield_token invocation; if the callee needs to store it, it has to make a copy. This is similar to serde, but avoids the ping-pong between Deserializer, *Access and Visitor. - No reliance on
'static
for metadata like struct field names.
The aim is for the implementation to be on a par with serde in terms of performance.
The name serser comes from the idea that serialization and deserialization are fundamentally the same thing, just switching perspectives of the source and sink. It is a conversion from one representation to another, through a common data model.
Dependencies
~0.5–1MB
~20K SLoC