.. /index

Serde Architecture

Serde Architecture

Serde's architecture is arguably the most brilliant design in the Rust ecosystem. Its "data model" of 29 types doesn't exist as an enum or intermediate structure — the data model is expressed entirely as methods on the Serializer and Deserializer traits. This achieves true zero-cost abstraction: no intermediate allocation, no format-agnostic representation sitting in memory.

How it works

#[derive(Serialize)] generates code that drives the serializer by calling trait methods: serialize_struct(), then serialize_field() for each field. Each format (JSON, Bincode, TOML) implements these trait methods differently. The derive macro generates direct method calls — there is no intermediate data structure.

The typestate-pattern enforces sequencing: serialize_struct consumes the serializer and returns a SerializeStruct type. Calling end() consumes that and produces a Result. Invalid sequencing (calling end before adding fields, adding fields after end) won't compile.

Dual extensibility

This design is extensible along two independent dimensions:

Neither requires modifying serde itself. This is the classic expression of the "expression problem" solved through traits — contrast with an enum-based data model where adding either a new type or a new format requires modifying the central enum.

Why it matters

Serde demonstrates that zero-cost abstraction at crate-architecture scale is possible when traits are used as the abstraction boundary. No runtime overhead, no boxing, no intermediate representations — just direct method calls generated by derive macros. This pattern of "traits as the data model" is serde's deepest contribution to Rust design thinking.

See expert-rust-design for the broader design philosophy and rkyv for a complementary approach (zero-copy deserialization rather than zero-allocation serialization).

Linked from

Sources