use crate::error::Error;
use alloc::vec;
use alloc::vec::Vec;
const NUMBER_SIZE: usize = 4;
pub(crate) const MOLECULE_SER: &str = "MoleculeSerializer";
pub(crate) const MOLECULE_DE: &str = "MoleculeDeserializer";
pub fn assemble_table(parts: &[Vec<u8>]) -> Vec<u8> {
let header_len = parts.len() + 1;
let mut header = vec![0u32; header_len];
let mut offset = (header_len * 4) as u32;
for i in 1..header_len {
header[i] = offset;
offset += parts[i - 1].len() as u32;
}
header[0] = offset;
let mut result = vec![];
header
.into_iter()
.map(|u| u.to_le_bytes().to_vec())
.fold(&mut result, |acc, item| {
acc.extend(item);
acc
});
parts.iter().fold(&mut result, |acc, item| {
acc.extend(item);
acc
});
result
}
pub fn assemble_fixvec(parts: &Vec<Vec<u8>>) -> Result<Vec<u8>, Error> {
if parts.len() > 1 {
let len = parts[0].len();
for item in parts {
if len != item.len() {
return Err(Error::AssembleFixvec);
}
}
}
if !parts.is_empty() && parts.iter().all(|e| e.is_empty()) {
return Err(Error::AssembleFixvec);
}
let mut result = vec![];
let len = parts.len() as u32;
result.extend(len.to_le_bytes());
parts.iter().fold(&mut result, |acc, item| {
acc.extend(item);
acc
});
Ok(result)
}
pub fn assemble_struct(parts: Vec<Vec<u8>>) -> Vec<u8> {
let mut result = vec![];
parts.into_iter().fold(&mut result, |acc, item| {
acc.extend(item);
acc
});
result
}
pub fn unpack_number(data: &[u8], offset: usize) -> Result<usize, Error> {
if data.len() < (4 + offset) {
Err(Error::LengthNotEnough)
} else {
let bytes: [u8; 4] = data[offset..offset + 4].try_into().unwrap();
Ok(u32::from_le_bytes(bytes) as usize)
}
}
pub fn disassemble_fixvec(data: &[u8]) -> Result<Vec<&[u8]>, Error> {
let item_count = unpack_number(data, 0)?;
if item_count == 0 {
return Ok(vec![]);
}
let remaining = data.len().checked_sub(4).ok_or(Error::Overflow)?;
if remaining == 0 {
return Err(Error::InvalidFixvec);
}
if remaining % item_count != 0 {
return Err(Error::InvalidFixvec);
}
let item_size = remaining / item_count;
let mut result = vec![];
for i in 0..item_count {
result.push(&data[4 + i * item_size..4 + (i + 1) * item_size]);
}
Ok(result)
}
pub fn disassemble_table(data: &[u8]) -> Result<Vec<&[u8]>, Error> {
let mut result = vec![];
let total_size = unpack_number(data, 0)?;
if data.len() != total_size {
return Err(Error::InvalidTableLength);
}
if total_size == NUMBER_SIZE {
return Ok(result);
}
if total_size < NUMBER_SIZE * 2 {
return Err(Error::InvalidTableLength);
}
let mut cur = 0;
cur += NUMBER_SIZE;
let first_offset = unpack_number(data, cur)?;
if first_offset % NUMBER_SIZE != 0 || first_offset < NUMBER_SIZE * 2 {
return Err(Error::InvalidTableHeader);
}
if total_size < first_offset {
return Err(Error::InvalidTableHeader);
}
let count = first_offset / 4 - 1;
let mut last_offset = first_offset;
let mut offset = first_offset;
cur += NUMBER_SIZE;
for _ in 1..count {
offset = unpack_number(data, cur)?;
if last_offset > offset {
return Err(Error::InvalidTable);
}
if offset > data.len() {
return Err(Error::InvalidTable);
}
result.push(&data[last_offset..offset]);
last_offset = offset;
cur += NUMBER_SIZE;
}
result.push(&data[offset..]);
Ok(result)
}