feat: add a function to read a "bloc / field size" in SSV memory
This commit is contained in:
parent
815333667a
commit
5ed52a657e
@ -1,5 +1,6 @@
|
||||
mod ssvlib_demo;
|
||||
mod libssv;
|
||||
mod ssv_memory;
|
||||
|
||||
fn main() {
|
||||
ssvlib_demo::demo();
|
||||
|
119
crates/sesam-vitale/src/ssv_memory.rs
Normal file
119
crates/sesam-vitale/src/ssv_memory.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* 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 {
|
||||
size: usize,
|
||||
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)
|
||||
}
|
||||
|
||||
#[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"
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user