use tiny_varint::{
encode_zigzag,
VarIntEncoder, VarIntDecoder, Error, varint_size
};
#[derive(Debug, PartialEq)]
struct SimpleMessage {
message_id: u64,
temperature: i16,
humidity: i8,
payload: [u8; 16],
}
impl SimpleMessage {
fn serialized_size(&self) -> usize {
let id_size = varint_size(self.message_id);
let mut temp_buf = [0u8; 10];
let temp_size = encode_zigzag(self.temperature, &mut temp_buf).unwrap();
let mut hum_buf = [0u8; 10];
let humidity_size = encode_zigzag(self.humidity, &mut hum_buf).unwrap();
let payload_len_size = varint_size(self.payload.len() as u64);
id_size + temp_size + humidity_size + payload_len_size + self.payload.len()
}
fn serialize(&self, buffer: &mut [u8]) -> Result<usize, Error> {
let mut encoder = VarIntEncoder::<u32>::new(buffer);
encoder.write(self.message_id as u32)?;
encoder.write_zigzag(self.temperature)?;
encoder.write_zigzag(self.humidity)?;
encoder.write(self.payload.len() as u32)?;
let current_offset = encoder.position();
if current_offset + self.payload.len() > buffer.len() {
return Err(Error::BufferTooSmall {
needed: current_offset + self.payload.len(),
actual: buffer.len(),
});
}
buffer[current_offset..current_offset + self.payload.len()]
.copy_from_slice(&self.payload);
Ok(current_offset + self.payload.len())
}
fn deserialize(bytes: &[u8]) -> Result<(Self, usize), Error> {
let mut decoder = VarIntDecoder::<u32>::new(bytes);
let message_id = decoder.read()? as u64;
let temperature = decoder.read_zigzag::<i16>()?;
let humidity = decoder.read_zigzag::<i8>()?;
let payload_len = decoder.read()? as usize;
if payload_len != 16 {
return Err(Error::InvalidEncoding);
}
let current_offset = decoder.position();
if current_offset + payload_len > bytes.len() {
return Err(Error::InputTooShort);
}
let mut payload = [0u8; 16];
payload.copy_from_slice(&bytes[current_offset..current_offset + payload_len]);
let final_offset = current_offset + payload_len;
let msg = SimpleMessage {
message_id,
temperature,
humidity,
payload,
};
Ok((msg, final_offset))
}
}
fn main() {
println!("=== Protocol Serialization Example ===\n");
let mut payload = [0u8; 16];
for i in 0..payload.len() {
payload[i] = (i * 10) as u8;
}
let original_msg = SimpleMessage {
message_id: 42,
temperature: -15,
humidity: 85,
payload,
};
println!("Original message: {:#?}", original_msg);
let expected_size = original_msg.serialized_size();
println!("Expected serialized size: {} bytes", expected_size);
let mut buffer = [0u8; 100];
let serialize_result = original_msg.serialize(&mut buffer);
match serialize_result {
Ok(size) => {
println!("Serialization successful, used {} bytes", size);
print!("Serialized bytes: [ ");
for i in 0..size {
print!("{:#04x} ", buffer[i]);
}
println!("]");
match SimpleMessage::deserialize(&buffer[0..size]) {
Ok((decoded_msg, decoded_size)) => {
println!("\nDecoded message: {:#?}", decoded_msg);
println!("Decoded byte size: {} bytes", decoded_size);
println!("\nOriginal message and decoded message match: {}",
original_msg == decoded_msg);
}
Err(e) => {
println!("Decoding failed: {:?}", e);
}
}
println!("\nSpace efficiency analysis:");
let fixed_size = 8 + 2 + 1 + 16; println!(" Using fixed-size encoding: {} bytes", fixed_size);
println!(" Using varint encoding: {} bytes", size);
println!(" Savings: {} bytes ({:.1}%)",
fixed_size - size,
((fixed_size - size) as f32 / fixed_size as f32) * 100.0);
}
Err(e) => {
println!("Serialization failed: {:?}", e);
}
}
println!("\n=== Example Complete ===");
}