serialize.rs

Overview

This file provides a custom binary serialization and deserialization framework tailored for the Chitchat system. The primary goals of this serialization format are to:

The file defines two core traits, Serializable and Deserializable, for encoding and decoding types, respectively. It also implements these traits for a range of standard and custom types. A key component is the CompressedStreamWriter, which manages block-based serialization with optional compression.


Traits

Serializable

Trait defining the interface for types that can be serialized into a byte buffer.

Deserializable

Trait defining the interface for types that can be deserialized from a byte slice.


Implementations of Serializable and Deserializable

The file provides implementations for primitive types, standard library types, and Chitchat-specific types:

Example: Serializing an IpAddr

let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let mut buf = Vec::new();
ip.serialize(&mut buf);
// buf will contain: [4, 127, 0, 0, 1] 

Example: Deserializing a SocketAddr

let mut buf: &[u8] = /* some byte slice */;
let socket_addr = SocketAddr::deserialize(&mut buf)?;

IpVersion Enum

Internal enumeration to represent IP address version (IPv4 or IPv6) during serialization.

Implements TryFrom<u8> for safe conversion from a byte to IpVersion.


BlockType Enum

Enumerates the types of blocks used in the compression stream:

Each variant is represented as a single byte (0, 1, or 2) and implements serialization/deserialization.


CompressedStreamWriter

Purpose

Manages the serialization of a sequence of Serializable items into a compressed stream with the following features:

Fields

Methods

with_block_threshold(block_threshold: u16) -> Self

Creates a new CompressedStreamWriter with the specified block size threshold.

serialized_len_upperbound_after<S: Serializable + ?Sized>(&self, item: &S) -> usize

Estimates an upper bound on the total serialized length after appending item.

append<S: Serializable + ?Sized>(&mut self, item: &S)

Appends a serializable item to the stream.

flush_block(&mut self)

Flushes the first block_threshold bytes from uncompressed_block.

finish(self) -> Vec<u8>

Finalizes the stream:


Function: deserialize_stream

fn deserialize_stream<D: Deserializable>(buf: &mut &[u8]) -> anyhow::Result<Vec<D>>

Deserializes a block-compressed stream from a byte buffer.


Implementation Details and Algorithms


Interaction with Other Parts of the System


Visual Diagram

classDiagram
class Serializable {
<<trait>>
+serialize(buf: &mut Vec<u8>)
+serialize_to_vec() Vec<u8>
+serialized_len() usize
}
class Deserializable {
<<trait>>
+deserialize(buf: &mut &[u8]) Result<Self>
}
class CompressedStreamWriter {
-output: Vec<u8>
-uncompressed_block: Vec<u8>
-compressed_block: Vec<u8>
-block_threshold: usize
+with_block_threshold(u16) CompressedStreamWriter
+serialized_len_upperbound_after(item: &Serializable) usize
+append(item: &Serializable)
-flush_block()
+finish() Vec<u8>
}
class BlockType {
<<enum>>
+NoMoreBlocks
+Compressed
+Uncompressed
+serialize(buf: &mut Vec<u8>)
+deserialize(buf: &mut &[u8]) Result<Self>
}
Serializable <|.. u8
Serializable <|.. u16
Serializable <|.. u32
Serializable <|.. u64
Serializable <|.. bool
Serializable <|.. IpAddr
Serializable <|.. SocketAddr
Serializable <|.. String
Serializable <|.. str
Serializable <|.. [u8; N]
Serializable <|.. ChitchatId
Serializable <|.. Heartbeat
Deserializable <|.. u8
Deserializable <|.. u16
Deserializable <|.. u32
Deserializable <|.. u64
Deserializable <|.. bool
Deserializable <|.. IpAddr
Deserializable <|.. SocketAddr
Deserializable <|.. String
Deserializable <|.. [u8; N]
Deserializable <|.. ChitchatId
Deserializable <|.. Heartbeat
CompressedStreamWriter --> Serializable : uses
deserialize_stream ..> Deserializable : uses
CompressedStreamWriter --> BlockType : manages blocks

Usage Examples

Serializing and Deserializing a ChitchatId

let id = ChitchatId::new("node-123".to_string(), 42, "127.0.0.1:8080".parse().unwrap());
let mut buffer = Vec::new();
id.serialize(&mut buffer);

let mut slice = &buffer[..];
let deserialized_id = ChitchatId::deserialize(&mut slice)?;
assert_eq!(id, deserialized_id);

Using CompressedStreamWriter to Serialize Multiple Items

let mut writer = CompressedStreamWriter::with_block_threshold(1024);

for message in messages {
    writer.append(&message);
}

let compressed_bytes = writer.finish();

// Send `compressed_bytes` over network or store.

Deserializing a Compressed Stream

let mut slice = &compressed_bytes[..];
let items: Vec<String> = deserialize_stream(&mut slice)?;

Testing

The file includes comprehensive unit tests and property-based tests to verify correctness of:

These tests validate the robustness and correctness of the serialization framework.


References