use multi_trait::{EncodeInto, EncodeIntoArray, EncodeIntoBuffer, TryDecodeFrom};
fn main() {
println!("=== Multitrait no_std Usage Patterns ===\n");
println!("Note: This example demonstrates no_std patterns");
println!("but runs with std for example execution.\n");
stack_based_encoding();
minimal_heap_usage();
fixed_size_buffers();
zero_allocation_decoding();
}
fn stack_based_encoding() {
println!("1. Stack-Based Encoding (Zero Heap)");
println!("------------------------------------");
let value = 42u8;
let (array, len) = value.encode_into_array();
println!("Encoded {} to stack array", value);
println!("Used {} byte(s) out of maximum {}", len, array.len());
println!("Array contents: {:?}", &array[..len]);
let (decoded, _) = u8::try_decode_from(&array[..len]).unwrap();
println!("Decoded: {}", decoded);
assert_eq!(value, decoded);
println!("\nStack encoding for different types:");
let (_array, len) = 1000u16.encode_into_array();
println!(" u16 (1000): {} byte(s)", len);
let (_array, len) = 100000u32.encode_into_array();
println!(" u32 (100000): {} byte(s)", len);
let (_array, len) = u64::MAX.encode_into_array();
println!(" u64::MAX: {} byte(s) (maximum for u64)", len);
println!();
}
fn minimal_heap_usage() {
println!("2. Minimal Heap Usage");
println!("---------------------");
let mut buffer = Vec::with_capacity(100);
let initial_capacity = buffer.capacity();
println!("Pre-allocated buffer capacity: {}", initial_capacity);
for i in 0u16..30 {
i.encode_into_buffer(&mut buffer);
}
println!("Encoded 30 values");
println!("Buffer length: {} bytes", buffer.len());
println!("Buffer capacity: {} (no reallocation!)", buffer.capacity());
assert_eq!(buffer.capacity(), initial_capacity);
let mut slice = &buffer[..];
let mut count = 0;
while !slice.is_empty() {
let (value, remaining) = u16::try_decode_from(slice).unwrap();
assert_eq!(value, count);
slice = remaining;
count += 1;
}
println!("Decoded {} values without allocation", count);
println!();
}
fn fixed_size_buffers() {
println!("3. Fixed-Size Buffers for Embedded");
println!("-----------------------------------");
const BUFFER_SIZE: usize = 64;
let mut buffer = [0u8; BUFFER_SIZE];
let mut offset = 0;
println!("Fixed-size buffer: {} bytes", BUFFER_SIZE);
let values = [10u16, 20, 30, 40, 50];
for value in values.iter() {
let (array, len) = value.encode_into_array();
buffer[offset..offset + len].copy_from_slice(&array[..len]);
offset += len;
}
println!("Encoded {} values", values.len());
println!("Used {} bytes out of {} available", offset, BUFFER_SIZE);
let mut slice = &buffer[..offset];
let mut decoded_values = Vec::new(); while !slice.is_empty() {
let (value, remaining) = u16::try_decode_from(slice).unwrap();
decoded_values.push(value);
slice = remaining;
}
println!("Decoded values: {:?}", decoded_values);
assert_eq!(decoded_values.as_slice(), &values);
println!();
}
fn zero_allocation_decoding() {
println!("4. Zero-Allocation Decoding");
println!("----------------------------");
let mut data = Vec::new(); for i in 0u32..10 {
data.extend_from_slice(&i.encode_into());
}
println!("Encoded 10 values in {} bytes", data.len());
println!("Data: {:?}", data);
let mut slice = &data[..];
let mut sum = 0u64;
let mut count = 0;
println!("\nDecoding values (no allocation):");
while !slice.is_empty() {
let (value, remaining) = u32::try_decode_from(slice).unwrap();
println!(" Value {}: {}", count, value);
sum += value as u64;
slice = remaining;
count += 1;
}
println!("\nDecoded {} values", count);
println!("Sum: {}", sum);
let expected_sum: u64 = (0..10).sum();
assert_eq!(sum, expected_sum);
println!();
}
#[allow(dead_code)]
mod no_std_custom_types {
use multi_trait::{EncodeIntoArray, EncodeIntoBuffer, TryDecodeFrom};
#[derive(Debug, PartialEq)]
pub struct SensorReading {
pub sensor_id: u8,
pub value: u16,
}
impl SensorReading {
pub fn encode_to_array(&self) -> ([u8; 19], usize) {
let (id_array, id_len) = self.sensor_id.encode_into_array();
let (val_array, val_len) = self.value.encode_into_array();
let mut result = [0u8; 19];
result[..id_len].copy_from_slice(&id_array[..id_len]);
result[id_len..id_len + val_len].copy_from_slice(&val_array[..val_len]);
(result, id_len + val_len)
}
pub fn decode_from(bytes: &[u8]) -> Result<(Self, &[u8]), multi_trait::Error> {
let (sensor_id, remaining) = u8::try_decode_from(bytes)?;
let (value, remaining) = u16::try_decode_from(remaining)?;
Ok((SensorReading { sensor_id, value }, remaining))
}
pub fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
self.sensor_id.encode_into_buffer(buffer);
self.value.encode_into_buffer(buffer);
}
}
}