use super::SchRecord;
use crate::error::AddContext;
use crate::{
sch::{pin::SchPin, record::parse_any_record},
Error,
};
pub fn parse_all_records(buf: &[u8], err_name: &str) -> Result<Vec<SchRecord>, Error> {
const TY_SHIFT: u32 = 24;
const TY_MAEK: u32 = 0xff000000;
const LEN_MASK: u32 = 0x00ffffff;
const UTF8_RECORD_TY: u32 = 0x00;
const PIN_RECORD_TY: u32 = 0x01;
const U32_BYTES: usize = 4;
let mut working = buf;
let mut parsed = Vec::new();
while !working.is_empty() {
assert!(
working.len() >= 4,
"expected at least 4 bytes, only got {}",
working.len()
);
let info = u32::from_le_bytes(working[..4].try_into().unwrap());
let ty = (info & TY_MAEK) >> TY_SHIFT;
let len: usize = (info & LEN_MASK).try_into().unwrap();
let to_parse = &working[U32_BYTES..(U32_BYTES + len - 1)];
assert_eq!(working[U32_BYTES + len - 1], 0, "Expected null terimation");
working = &working[U32_BYTES + len..];
let record = match ty {
UTF8_RECORD_TY => parse_any_record(to_parse),
PIN_RECORD_TY => SchPin::parse(to_parse).map_err(Into::into),
_ => panic!("unexpected record type {ty:02x}"),
};
parsed.push(record.or_context(|| format!("in `parse_all_records` for `{err_name}`"))?);
}
Ok(parsed)
}