165 lines
4.8 KiB
Rust
165 lines
4.8 KiB
Rust
/**
|
|
* 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<ElementSize, MemoryParsingError> {
|
|
/* 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<u8>,
|
|
}
|
|
|
|
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);
|
|
}
|
|
} |