use crate::error::{Error, Result};
use crate::model::Model;
const HEADER: usize = 196;
const RECORD: usize = 44;
const FP32: u8 = 2;
const MANIFEST_VALUES: u32 = 13;
const MANIFEST_RATE: (usize, f32) = (9, 16_000.0);
pub(crate) const MAGIC: u32 = 0x05E1_2A84;
pub(crate) fn check_magic(bytes: &[u8]) -> Result<()> {
let Some(&[a, b, c, d]) = bytes.get(..4) else {
return Err(Error::UnsupportedWeights { tag: 0 });
};
let tag = u32::from_le_bytes([a, b, c, d]);
if tag == MAGIC {
Ok(())
} else {
Err(Error::UnsupportedWeights { tag })
}
}
pub(crate) fn kind_of(bytes: &[u8]) -> Option<Model> {
if read_u32(bytes, 0)? != MAGIC {
return None;
}
let count = usize::try_from(read_u32(bytes, 4)?).ok()?;
let codebook = usize::try_from(read_u32(bytes, 8)?).ok()?;
let start = codebook.checked_mul(4)?.checked_add(HEADER)?;
let end = count.checked_mul(RECORD)?.checked_add(start)?;
let directory = bytes.get(start..end)?;
for record in directory.chunks_exact(RECORD) {
if is_manifest(bytes, record)? {
return Some(Model::Whistle);
}
}
Some(Model::Needle)
}
fn is_manifest(bytes: &[u8], record: &[u8]) -> Option<bool> {
let shaped = record.first() == Some(&FP32)
&& record.get(1) == Some(&1)
&& read_u32(record, 4)? == MANIFEST_VALUES
&& read_u64(record, 28)? == u64::from(MANIFEST_VALUES) * 4;
if !shaped {
return Some(false);
}
let offset = usize::try_from(read_u64(record, 20)?).ok()?;
let (index, rate) = MANIFEST_RATE;
let at = index.checked_mul(4)?.checked_add(offset)?;
bytes.get(offset..offset.checked_add(MANIFEST_VALUES as usize * 4)?)?;
let value = f32::from_bits(read_u32(bytes, at)?);
Some(value.to_bits() == rate.to_bits())
}
fn read_u32(bytes: &[u8], at: usize) -> Option<u32> {
let word = bytes.get(at..at.checked_add(4)?)?;
Some(u32::from_le_bytes(word.try_into().ok()?))
}
fn read_u64(bytes: &[u8], at: usize) -> Option<u64> {
let word = bytes.get(at..at.checked_add(8)?)?;
Some(u64::from_le_bytes(word.try_into().ok()?))
}
#[cfg(test)]
mod tests {
use super::*;
fn archive(count: u32, records: &[[u8; RECORD]], data: &[u8]) -> Vec<u8> {
let mut bytes = vec![0_u8; HEADER];
bytes[..4].copy_from_slice(&MAGIC.to_le_bytes());
bytes[4..8].copy_from_slice(&count.to_le_bytes());
for record in records {
bytes.extend_from_slice(record);
}
bytes.extend_from_slice(data);
bytes
}
fn record(dtype: u8, ndim: u8, dim0: u32, offset: u64, size: u64) -> [u8; RECORD] {
let mut record = [0_u8; RECORD];
record[0] = dtype;
record[1] = ndim;
record[4..8].copy_from_slice(&dim0.to_le_bytes());
record[20..28].copy_from_slice(&offset.to_le_bytes());
record[28..36].copy_from_slice(&size.to_le_bytes());
record
}
fn manifest(rate: f32) -> Vec<u8> {
(0..13)
.map(|i| if i == 9 { rate } else { i as f32 })
.flat_map(f32::to_le_bytes)
.collect()
}
fn data_at(count: usize) -> u64 {
(HEADER + count * RECORD) as u64
}
#[test]
fn an_audio_manifest_makes_a_whistle() {
let records = [
record(FP32, 2, 64, 0, 0),
record(FP32, 1, 13, data_at(2), 52),
];
let bytes = archive(2, &records, &manifest(16_000.0));
assert_eq!(kind_of(&bytes), Some(Model::Whistle));
}
#[test]
fn no_manifest_makes_a_needle() {
let records = [record(FP32, 2, 64, 0, 0)];
assert_eq!(kind_of(&archive(1, &records, &[])), Some(Model::Needle));
assert_eq!(kind_of(&archive(0, &[], &[])), Some(Model::Needle));
let records = [record(FP32, 1, 13, data_at(1), 52)];
let bytes = archive(1, &records, &manifest(22_050.0));
assert_eq!(kind_of(&bytes), Some(Model::Needle));
}
#[test]
fn a_truncated_directory_is_no_archive() {
let records = [record(FP32, 2, 64, 0, 0)];
assert_eq!(kind_of(&archive(2, &records, &[])), None);
assert_eq!(kind_of(&MAGIC.to_le_bytes()), None);
assert_eq!(kind_of(&[]), None);
}
#[test]
fn a_manifest_pointing_outside_the_archive_is_no_archive() {
let records = [record(FP32, 1, 13, data_at(1), 52)];
let mut bytes = archive(1, &records, &manifest(16_000.0));
bytes.truncate(bytes.len() - 1);
assert_eq!(kind_of(&bytes), None);
let records = [record(FP32, 1, 13, u64::MAX - 4, 52)];
assert_eq!(kind_of(&archive(1, &records, &[])), None);
}
#[test]
fn a_huge_count_is_refused_without_a_panic() {
assert_eq!(kind_of(&archive(u32::MAX, &[], &[])), None);
let mut bytes = archive(0, &[], &[]);
bytes[8..12].copy_from_slice(&u32::MAX.to_le_bytes());
assert_eq!(kind_of(&bytes), None);
}
#[test]
fn the_wrong_tag_is_no_archive() {
let mut bytes = archive(0, &[], &[]);
bytes[0] = 0x83;
assert_eq!(kind_of(&bytes), None);
}
#[test]
fn the_pinned_archives_are_told_apart() {
for (variable, model) in [
("CACTUS_NEEDLE_WEIGHTS", Model::Needle),
("CACTUS_WHISTLE_WEIGHTS", Model::Whistle),
] {
let Some(bytes) = std::env::var_os(variable).and_then(|path| std::fs::read(path).ok())
else {
println!("skipping the {model} archive kind test: set {variable} to run it");
continue;
};
assert_eq!(kind_of(&bytes), Some(model), "{variable}");
}
}
#[test]
fn the_magic_tag_is_accepted() {
assert!(check_magic(&[0x84, 0x2A, 0xE1, 0x05]).is_ok());
assert!(check_magic(&[0x84, 0x2A, 0xE1, 0x05, 0xFF]).is_ok());
}
#[test]
fn another_tag_is_reported() {
let error = check_magic(&[0x83, 0x2A, 0xE1, 0x05]).expect_err("a Needle 2 tag");
assert!(matches!(
error,
Error::UnsupportedWeights { tag: 0x05E1_2A83 }
));
}
#[test]
fn a_short_header_reports_tag_zero() {
let error = check_magic(&[0x84, 0x2A, 0xE1]).expect_err("three bytes");
assert!(matches!(error, Error::UnsupportedWeights { tag: 0 }));
}
}