/** * 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) } pub struct Element { pub pad: usize, pub contenu: Vec, } pub fn read_element(bytes: &[u8]) -> Element { let ElementSize { size, pad } = read_element_size(bytes).unwrap(); let contenu = bytes[pad..pad+size].to_vec(); Element { pad: pad+size, contenu, } } #[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" )), ); } } #[cfg(test)] mod test_read_element { use super::*; #[test] fn short_size() { let bytes = [51, 1, 48, 1, 56, 11, 57, 57, 55, 48, 48, 53, 50, 52, 49, 57, 52, 1, 52, 2, 50, 50, 17, 80, 72, 65, 82, 77, 65, 67, 73, 69, 78, 48, 48, 53, 50, 52, 49, 57, 9, 70, 82, 65, 78, 67, 79, 73, 83, 69, 1, 84, ]; let element = read_element(&bytes); assert_eq!(element.pad, 52); assert_eq!(element.contenu[..5], [1, 48, 1, 56, 11]); } #[test] fn long_size() { let mut bytes = vec![0b_1000_0010_u8, 0b_0000_0001_u8, 0b_0000_0000_u8, // size = 256 ]; // Add 256 bytes to the content bytes.append(&mut vec![1; 256]); let element = read_element(&bytes); assert_eq!(element.pad, 259); assert_eq!(element.contenu.len(), 256); } }