Expand description
Serialization and deserialization for the nix remote protocol.
The protocol has two primitive types: integers and byte buffers. All integers are encoded in 64 bits (little endian). I haven’t seen signed integers appear in the protocol yet, but presumably they’re encoded in twos complement. Byte buffers are encoded as a length (64-bit integer), followed by the bytes in the buffer. If the length of the buffer is not a multiple of 8, it is zero-padded to a multiple of 8 bytes.
The Nix source parses the protocol imperatively, but there are some common patterns that we implement declaratively with the help of serde’s derive macros:
- structs and tuples are serialized as the concatenation of their fields (Nix does this manually for each struct)
- sequences (like
Vec
s) are serialized as a length followed by the concatenation of the elements (Nix has functions likereadStrings
for this).
So for example, the struct
pub struct BuildPathsWithResults {
paths: Vec<ByteBuf>,
build_mode: u64,
}
gets serde-derived serialization implementations that encode it as:
- the number of paths (an int)
- the paths concatenated together, each of which consists of
- a length (an int)
- a byte buffer of that length
- the build mode (an int)
Nix also has some sort of implicit “tagged union”, consisting of a type tag (and integer)
followed by a body. This serializer does not have built-in support for that, because serde
enums are built on string-valued tags (whereas the nix protocol wants integer tags).
Instead, we have a separate tagged_serde
macro for transforming enums into tuples.
Structs§
- NixDeserializer
- A deserializer for the nix remote protocol.
- NixSerializer
- A serializer for the nix remote protocol.
- Tee