pub mod apr2;
mod compress;
pub mod export;
#[cfg(all(feature = "cli", feature = "converter"))]
pub mod gguf_loader;
pub mod safetensors_loader;
pub mod validation;
pub mod whisper_metadata;
pub use aprender::format::v2::{
align_64, align_up, AprV2Flags, AprV2Header, AprV2Metadata, AprV2Reader, AprV2ReaderRef,
AprV2Writer, TensorDType, TensorIndexEntry, ALIGNMENT, HEADER_SIZE_V2, LZ4_BLOCK_SIZE,
MAGIC_V2, MAX_METADATA_SIZE, MAX_TENSOR_NAME_LEN, VERSION_V2,
};
pub use apr2::{
Apr2Header, Apr2Quantization, Apr2Reader, Apr2TensorData, Apr2TensorDescriptor, Apr2Writer,
FfnActivation, LayerType, Lfm2Config, Lfm2WasmConfig, ModelFamily, QuantConfig, APR2_VERSION,
MAGIC_APR2,
};
pub use compress::Decompressor;
#[cfg(all(feature = "cli", feature = "converter"))]
pub use gguf_loader::{load_gguf_whisper, map_gguf_whisper_tensor_name};
#[cfg(feature = "cli")]
pub use safetensors_loader::SafeTensorsLoader;
pub use safetensors_loader::{
map_moonshine_tensor_name, map_tensor_name, ConversionStats, WeightMapping,
};
pub use validation::{
quick_validate, validate_apr_bytes, AprValidator, TensorStats, ValidationCheck,
ValidationReport,
};
#[cfg(any(feature = "converter", test))]
pub use whisper_metadata::{build_whisper_metadata, create_test_apr};
pub use whisper_metadata::{metadata_to_model_config, MelFilterbankData};
const CRC32_TABLE: [u32; 256] = {
let mut table = [0u32; 256];
let mut i = 0usize;
while i < 256 {
let mut crc = i as u32;
let mut j = 0;
while j < 8 {
crc = if crc & 1 != 0 {
(crc >> 1) ^ 0xEDB8_8320
} else {
crc >> 1
};
j += 1;
}
table[i] = crc;
i += 1;
}
table
};
#[must_use]
pub fn crc32(data: &[u8]) -> u32 {
let mut crc: u32 = 0xFFFF_FFFF;
for &byte in data {
let idx = ((crc ^ u32::from(byte)) & 0xFF) as usize;
crc = (crc >> 8) ^ CRC32_TABLE[idx];
}
!crc
}
#[cfg(test)]
mod crc32_tests {
use super::crc32;
#[test]
fn test_crc32_known_vector() {
assert_eq!(crc32(b"123456789"), 0xCBF4_3926);
}
#[test]
fn test_crc32_empty() {
assert_eq!(crc32(b""), 0);
}
#[test]
fn test_crc32_matches_reference_bitwise() {
fn bitwise(data: &[u8]) -> u32 {
let mut crc: u32 = 0xFFFF_FFFF;
for &byte in data {
crc ^= u32::from(byte);
for _ in 0..8 {
crc = if crc & 1 != 0 {
(crc >> 1) ^ 0xEDB8_8320
} else {
crc >> 1
};
}
}
!crc
}
for len in [0usize, 1, 2, 7, 16, 255, 1024] {
let data: Vec<u8> = (0..len).map(|i| (i * 31 + 7) as u8).collect();
assert_eq!(crc32(&data), bitwise(&data), "mismatch at len {len}");
}
}
}