protocol_serialization/
protocol_serialization.rs

1//! Protocol Serialization Example
2//! 
3//! This example demonstrates how to combine tiny-varint with custom protocol serialization
4//! Using APIs that don't require dynamic memory allocation
5//! Run with: cargo run --example protocol_serialization
6
7use tiny_varint::{
8    encode_zigzag,
9    VarIntEncoder, VarIntDecoder, Error, varint_size
10};
11
12/// A simple message structure that can be serialized and deserialized
13#[derive(Debug, PartialEq)]
14struct SimpleMessage {
15    // Message ID encoded as varint (typically small numbers)
16    message_id: u64,
17    
18    // Temperature value encoded using zigzag (can be positive or negative)
19    temperature: i16,
20    
21    // Humidity value encoded using zigzag (0-100 positive, but using zigzag for consistency)
22    humidity: i8,
23    
24    // Payload data
25    payload: [u8; 16],
26}
27
28impl SimpleMessage {
29    /// Calculate the serialized size
30    fn serialized_size(&self) -> usize {
31        // Number of bytes needed
32        let id_size = varint_size(self.message_id);
33        
34        // Create temporary buffers for temperature and humidity to calculate size
35        let mut temp_buf = [0u8; 10];
36        let temp_size = encode_zigzag(self.temperature, &mut temp_buf).unwrap();
37        
38        let mut hum_buf = [0u8; 10];
39        let humidity_size = encode_zigzag(self.humidity, &mut hum_buf).unwrap();
40        
41        // Payload size needs a length field + the payload itself
42        let payload_len_size = varint_size(self.payload.len() as u64);
43        
44        id_size + temp_size + humidity_size + payload_len_size + self.payload.len()
45    }
46    
47    /// Serialize message to byte array
48    fn serialize(&self, buffer: &mut [u8]) -> Result<usize, Error> {
49        // Use VarIntEncoder for serialization
50        let mut encoder = VarIntEncoder::<u32>::new(buffer);
51        
52        // Serialize message ID (varint) - using u32 implementation instead of u64
53        encoder.write(self.message_id as u32)?;
54        
55        // Serialize temperature (zigzag varint)
56        encoder.write_zigzag(self.temperature)?;
57        
58        // Serialize humidity (zigzag varint)
59        encoder.write_zigzag(self.humidity)?;
60        
61        // Serialize payload length
62        encoder.write(self.payload.len() as u32)?;
63        
64        // Write payload bytes
65        let current_offset = encoder.position();
66        if current_offset + self.payload.len() > buffer.len() {
67            return Err(Error::BufferTooSmall {
68                needed: current_offset + self.payload.len(),
69                actual: buffer.len(),
70            });
71        }
72        
73        buffer[current_offset..current_offset + self.payload.len()]
74            .copy_from_slice(&self.payload);
75            
76        Ok(current_offset + self.payload.len())
77    }
78    
79    /// Deserialize message from byte array
80    fn deserialize(bytes: &[u8]) -> Result<(Self, usize), Error> {
81        let mut decoder = VarIntDecoder::<u32>::new(bytes);
82        
83        // Decode message ID
84        let message_id = decoder.read()? as u64;
85        
86        // Decode temperature
87        let temperature = decoder.read_zigzag::<i16>()?;
88        
89        // Decode humidity
90        let humidity = decoder.read_zigzag::<i8>()?;
91        
92        // Decode payload length
93        let payload_len = decoder.read()? as usize;
94        if payload_len != 16 {
95            return Err(Error::InvalidEncoding);
96        }
97        
98        // Decode payload
99        let current_offset = decoder.position();
100        if current_offset + payload_len > bytes.len() {
101            return Err(Error::InputTooShort);
102        }
103        
104        let mut payload = [0u8; 16];
105        payload.copy_from_slice(&bytes[current_offset..current_offset + payload_len]);
106        
107        let final_offset = current_offset + payload_len;
108        
109        let msg = SimpleMessage {
110            message_id,
111            temperature,
112            humidity,
113            payload,
114        };
115        
116        Ok((msg, final_offset))
117    }
118}
119
120fn main() {
121    println!("=== Protocol Serialization Example ===\n");
122    
123    // Create an example message
124    let mut payload = [0u8; 16];
125    for i in 0..payload.len() {
126        payload[i] = (i * 10) as u8;
127    }
128    
129    let original_msg = SimpleMessage {
130        message_id: 42,
131        temperature: -15,
132        humidity: 85,
133        payload,
134    };
135    
136    println!("Original message: {:#?}", original_msg);
137    
138    // Calculate serialization size
139    let expected_size = original_msg.serialized_size();
140    println!("Expected serialized size: {} bytes", expected_size);
141    
142    // Serialize message
143    let mut buffer = [0u8; 100];
144    let serialize_result = original_msg.serialize(&mut buffer);
145    
146    match serialize_result {
147        Ok(size) => {
148            println!("Serialization successful, used {} bytes", size);
149            
150            print!("Serialized bytes: [ ");
151            for i in 0..size {
152                print!("{:#04x} ", buffer[i]);
153            }
154            println!("]");
155            
156            // Deserialize message
157            match SimpleMessage::deserialize(&buffer[0..size]) {
158                Ok((decoded_msg, decoded_size)) => {
159                    println!("\nDecoded message: {:#?}", decoded_msg);
160                    println!("Decoded byte size: {} bytes", decoded_size);
161                    
162                    println!("\nOriginal message and decoded message match: {}", 
163                        original_msg == decoded_msg);
164                }
165                Err(e) => {
166                    println!("Decoding failed: {:?}", e);
167                }
168            }
169            
170            // Space efficiency analysis
171            println!("\nSpace efficiency analysis:");
172            let fixed_size = 8 + 2 + 1 + 16; // u64 + i16 + i8 + payload
173            println!("  Using fixed-size encoding: {} bytes", fixed_size);
174            println!("  Using varint encoding: {} bytes", size);
175            println!("  Savings: {} bytes ({:.1}%)", 
176                fixed_size - size, 
177                ((fixed_size - size) as f32 / fixed_size as f32) * 100.0);
178        }
179        Err(e) => {
180            println!("Serialization failed: {:?}", e);
181        }
182    }
183    
184    println!("\n=== Example Complete ===");
185}