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 ssvlib_demo;
|
||||||
mod libssv;
|
mod libssv;
|
||||||
|
mod ssv_memory;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
ssvlib_demo::demo();
|
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