/** * Provide functions to manipulate raw memory from SSV library. */ // TODO : Est-ce qu'on pourrait/devrait définir un type custom pour représenter les tableaux de bytes ? #[derive(PartialEq, Debug)] pub struct ElementSize { pub size: usize, pub pad: usize, } #[derive(PartialEq, Debug)] pub enum MemoryParsingError<'a> { MemoryIsEmpty(&'a str), MemoryIsNotValid(&'a str), } pub fn read_element_size(bytes: &[u8]) -> Result { /* Longueur: * - si le bit de poids fort du premier octet est à 0, la longueur est codée sur un octet * - si le bit de poids fort du premier octet est à 1, les 7 bits de poids faible codent le nombre d'octets utilisés pour coder la longueur */ if bytes.len() == 0 { return Err(MemoryParsingError::MemoryIsEmpty("Empty bytes input")); } let mut element_size = ElementSize { size: 0, pad: 1 }; if bytes[0] & 0b1000_0000 == 0 { // Size coded on 1 byte element_size.size = bytes[0] as usize; } else { // Size coded on N bytes // N are the 7 lower bits of the first byte let size_bytes_len = (bytes[0] & 0b0111_1111) as usize; if size_bytes_len > bytes.len() - 1 { return Err(MemoryParsingError::MemoryIsNotValid( "Invalid memory: not enough bytes to read the size", )); } else if size_bytes_len > 4 { return Err(MemoryParsingError::MemoryIsNotValid( "Invalid memory: size is too big", )); } let size_bytes = &bytes[1..1 + size_bytes_len]; // u32::from_be_bytes() requires a 4 bytes array let mut padded_bytes = [0u8; 4]; padded_bytes[size_bytes_len..].copy_from_slice(&size_bytes); element_size.size = u32::from_be_bytes(padded_bytes) as usize; element_size.pad += size_bytes_len; } Ok(element_size) } #[cfg(test)] mod test_read_element_size { use super::*; #[test] fn short_size() { let bytes = [0b_0000_0001_u8]; let element_size = read_element_size(&bytes).unwrap(); assert_eq!(element_size.size, 1); assert_eq!(element_size.pad, 1); let bytes = [0b_0100_0000_u8]; let element_size = read_element_size(&bytes).unwrap(); assert_eq!(element_size.size, 64); assert_eq!(element_size.pad, 1); } #[test] fn long_size() { let bytes = [0b_1000_0010_u8, 0b_0000_0001_u8, 0b_0100_0000_u8]; let element_size = read_element_size(&bytes).unwrap(); assert_eq!(element_size.size, 320); assert_eq!(element_size.pad, 3); } #[test] fn null_size() { let bytes = []; let toto = "toto"; // Expect an error assert_eq!( read_element_size(&bytes), Err(MemoryParsingError::MemoryIsEmpty("Empty bytes input")), ); } #[test] fn invalid_memory() { let bytes = [0b_1000_0001_u8]; assert_eq!( read_element_size(&bytes), Err(MemoryParsingError::MemoryIsNotValid( "Invalid memory: not enough bytes to read the size" )), ); let bytes = [0b_1000_0010_u8, 1]; assert_eq!( read_element_size(&bytes), Err(MemoryParsingError::MemoryIsNotValid( "Invalid memory: not enough bytes to read the size" )), ); let bytes = [0b_1000_0101_u8, 1, 1, 1, 1, 1]; assert_eq!( read_element_size(&bytes), Err(MemoryParsingError::MemoryIsNotValid( "Invalid memory: size is too big" )), ); } }