ser_raw/lib.rs
1//! # ser_raw
2//!
3//! `ser_raw` is a simple and fast serializer.
4//!
5//! It uses Rust's native memory layouts as the serialization format, so
6//! serializing is largely as simple as just copying raw bytes. This offers two
7//! main advantages:
8//!
9//! 1. The simplicity means it's very fast.
10//! 2. Deserialization can be zero-copy and instantaneous - just cast a pointer
11//! to the serialized data into a `&T`.
12//!
13//! The primary target for this library is sharing data between different
14//! processes on the same machine (including between different languages), but
15//! it can also be used for other purposes.
16//!
17//! # How fast is it?
18//!
19//! Fast! Benchmark of serializing a large AST structure produced by [SWC]:
20//!
21//! ```txt
22//! serde_json: 226.99 µs
23//! rkyv: 44.98 µs
24//! ser_raw: 14.35 µs
25//! ```
26//!
27//! # Serializers
28//!
29//! This crate provides 4 different serializers for different use cases. They
30//! offer a range of options, between doing work during serialization, or during
31//! deserialization. They mostly differ in how they deal with pointers.
32//!
33//! [`PureCopySerializer`] is the fastest and simplest serializer. Does not
34//! correct pointers, so the data can only be deserialized by traversing the
35//! tree of values in order.
36//!
37//! [`UnalignedSerializer`] is identical to [`PureCopySerializer`], except that
38//! it doesn't attempt to correctly align data.
39//!
40//! [`PtrOffsetSerializer`] replaces pointers in the input (e.g. in `Box`, `Vec`
41//! or `String`) with offsets. i.e. what byte index the pointee is located in
42//! the output.
43//!
44//! This allows lazy deserialization, and for a deserializer to traverse the
45//! tree of values in any order/direction.
46//!
47//! [`CompleteSerializer`] replaces pointers in the input with valid pointers
48//! into the output, and makes other corrections to ensure output is a
49//! completely valid representation of the input. Input can be "rehydrated" just
50//! by casting a pointer to the start of the output buffer as a `&T`.
51//!
52//! # Custom serializers
53//!
54//! This crate provides an easy-to-use [derive
55//! macro](ser_raw_derive_serializer::Serializer) to create custom
56//! [`Serializer`]s, based on any of the above.
57//!
58//! Serializers can also choose between different backing storage options.
59//! This crate provides two - [`AlignedVec`] and [`UnalignedVec`] - or it's
60//! possible to build your own [`Storage`] implementation.
61//!
62//! # Serializable types
63//!
64//! Only owned, sized types are supported at present.
65//!
66//! Support for serializing common Rust types (e.g. `u8`, `isize`, `NonZeroU32`,
67//! `Box`, `Vec`, `String`, `Option`) is included out of the box.
68//!
69//! For your own types, implement the [`Serialize`] trait. Usually, you can use
70//! the [derive macro](ser_raw_derive::Serialize).
71//!
72//! ```
73//! use ser_raw::Serialize;
74//!
75//! #[derive(Serialize)]
76//! struct Foo {
77//! small: u8,
78//! vec: Vec<u32>
79//! }
80//! ```
81//!
82//! For foreign types (i.e. from external crates), use [`SerializeWith`].
83//!
84//! # Deserializing
85//!
86//! No deserializers are provided at present.
87//!
88//! [`CompleteSerializer`] doesn't require a deserializer anyway, as you can
89//! just cast a pointer to the output buffer to a `&T`.
90//!
91//! # Warning
92//!
93//! As serializers just copy Rust's memory verbatim, a serializer's output
94//! will depend on the system it's run on (processor architecture, big endian or
95//! little endian, 64 bit or 32 bit).
96//!
97//! Rust also offers no guarantee that even the same code compiled twice on the
98//! same system will result in the same memory layouts (in practice it does, but
99//! you can always tag your types `#[repr(C)]` to make sure).
100//!
101//! Therefore, great care should be taken to ensure deserialization occurs on
102//! same type of machine as serialization occured on, and ideally using the same
103//! binary. A mismatch will be very likely to cause memory unsafety and the
104//! dreaded *undefined behavior*.
105//!
106//! For the primary use case for `ser_raw` - transfer of data within a single
107//! system - these constraints are not a problem.
108//!
109//! # Features
110//!
111//! `derive` feature enables the [`Serialize`] derive macro. Enabled by default.
112//!
113//! # Future direction and motivation
114//!
115//! The primary motivator for creating this library is to enable fast sharing of
116//! data between Rust and JavaScript (via [napi-rs]). The classic approach of
117//! using [serde JSON] is [much too slow] for some use cases, and [rkyv] turned
118//! out also to be slower than expected.
119//!
120//! The idea is to use [layout_inspect] to produce a schema of Rust's type
121//! layouts, and to use that schema to generate a matching JavaScript serializer
122//! / deserializer in which can deserialize `ser_raw`'s output.
123//!
124//! This is the main reason why there aren't deserializers implemented in Rust
125//! yet! I'm planning to be doing the deserialization in JavaScript.
126//!
127//! # Credits
128//!
129//! `ser_raw` follows the same approach to serialization as [abomonation]. It
130//! matches abomonation's extremely fast speed, while aiming to avoid its safety
131//! issues (and halloween theme!)
132//!
133//! [rkyv] is also an inspiration, and the backing storage used by most of
134//! `ser_raw`'s serializers, [`AlignedVec`], is based on [rkyv]'s type of
135//! the same name.
136//!
137//! [`AlignedVec`]: storage::AlignedVec
138//! [`UnalignedVec`]: storage::UnalignedVec
139//! [`Storage`]: storage::Storage
140//! [SWC]: https://swc.rs/
141//! [napi-rs]: https://napi.rs/
142//! [serde JSON]: https://serde.rs/
143//! [much too slow]: https://github.com/swc-project/swc/issues/2175
144//! [layout_inspect]: https://github.com/overlookmotel/layout_inspect
145//! [abomonation]: https://github.com/TimelyDataflow/abomonation
146//! [rkyv]: https://rkyv.org/
147
148// Derive macros
149#[cfg(feature = "derive")]
150pub use ser_raw_derive::Serialize;
151pub use ser_raw_derive_serializer::Serializer;
152
153// Export Serializers, Storage, traits, and utils
154mod serializer;
155pub use serializer::Serializer;
156
157mod serializers;
158pub use serializers::{
159 CompleteSerializer, PtrOffsetSerializer, PureCopySerializer, UnalignedSerializer,
160};
161
162mod serializer_traits;
163pub mod ser_traits {
164 //! Traits which are composed to create Serializers. Used internally by
165 //! [`Serializer`](crate::Serializer) derive macro.
166 pub use super::serializer_traits::*;
167}
168
169mod serialize;
170pub use serialize::{Serialize, SerializeWith};
171
172pub mod pos;
173pub mod storage;
174pub mod util;
175
176// `Serialize` implementations for Rust internal types
177mod serialize_impls;