macro_rules! define_le_pod_module {
(
$(#[$module_meta:meta])*
$vis:vis mod $mod_name:ident;
ty $elem:ty;
elem_size: $elem_size:expr;
read_fn: $read_fn:ident;
cast_fn: $cast_fn:ident;
count_fn: $count_fn:ident;
type_name: $type_name:literal;
) => {
$(#[$module_meta])*
$vis mod $mod_name {
#[inline]
#[must_use]
pub fn $read_fn(bytes: &[u8], i: usize) -> $elem {
let off = i
.checked_mul($elem_size)
.expect(concat!($type_name, " index overflow in ", stringify!($read_fn)));
debug_assert!(off + $elem_size <= bytes.len());
bytemuck::pod_read_unaligned::<$elem>(&bytes[off..off + $elem_size])
}
#[must_use]
pub fn $cast_fn(bytes: &[u8]) -> Option<&[$elem]> {
if !bytes.len().is_multiple_of($elem_size) {
return None;
}
bytemuck::try_cast_slice(bytes).ok()
}
#[must_use]
pub const fn $count_fn(bytes_len: usize) -> Option<usize> {
if bytes_len.is_multiple_of($elem_size) {
Some(bytes_len / $elem_size)
} else {
None
}
}
#[must_use]
pub const fn bytes_from_elem_count(count: u64) -> Option<u64> {
count.checked_mul($elem_size as u64)
}
}
};
}
define_le_pod_module! {
#[allow(dead_code)]
#[doc = "Little-endian `f32` views into chunk payloads.\n\n\
Layout v1 writers place the first payload at an **8-byte-aligned** file offset; each raw \
`f32` tile has a byte length divisible by **4**. Mmap subslices are not always 4-byte \
aligned (e.g. after variable-size zstd chunks), so per-element reads use \
[`bytemuck::pod_read_unaligned`]. When alignment and length allow it, [`try_cast_f32_le`] \
exposes a zero-copy `&[f32]` slice."]
pub mod f32_le;
ty f32;
elem_size: 4;
read_fn: read_f32_le_at;
cast_fn: try_cast_f32_le;
count_fn: f32_count;
type_name: "f32";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod f64_le;
ty f64;
elem_size: 8;
read_fn: read_f64_le_at;
cast_fn: try_cast_f64_le;
count_fn: f64_count;
type_name: "f64";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod i32_le;
ty i32;
elem_size: 4;
read_fn: read_i32_le_at;
cast_fn: try_cast_i32_le;
count_fn: i32_count;
type_name: "i32";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod i64_le;
ty i64;
elem_size: 8;
read_fn: read_i64_le_at;
cast_fn: try_cast_i64_le;
count_fn: i64_count;
type_name: "i64";
}
define_le_pod_module! {
#[allow(clippy::int_plus_one, dead_code)]
pub(crate) mod u8_le;
ty u8;
elem_size: 1;
read_fn: read_u8_le_at;
cast_fn: try_cast_u8_le;
count_fn: u8_count;
type_name: "u8";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod u16_le;
ty u16;
elem_size: 2;
read_fn: read_u16_le_at;
cast_fn: try_cast_u16_le;
count_fn: u16_count;
type_name: "u16";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod i16_le;
ty i16;
elem_size: 2;
read_fn: read_i16_le_at;
cast_fn: try_cast_i16_le;
count_fn: i16_count;
type_name: "i16";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod u32_le;
ty u32;
elem_size: 4;
read_fn: read_u32_le_at;
cast_fn: try_cast_u32_le;
count_fn: u32_count;
type_name: "u32";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod u64_le;
ty u64;
elem_size: 8;
read_fn: read_u64_le_at;
cast_fn: try_cast_u64_le;
count_fn: u64_count;
type_name: "u64";
}
define_le_pod_module! {
#[allow(dead_code)]
pub(crate) mod f16_le;
ty half::f16;
elem_size: 2;
read_fn: read_f16_le_at;
cast_fn: try_cast_f16_le;
count_fn: f16_count;
type_name: "f16";
}