pub(crate) fn decode_be<const N: usize, T, F>(bytes: &[u8], conv: F) -> Vec<T>
where
F: Fn([u8; N]) -> T,
{
bytes
.chunks_exact(N)
.map(|c| conv(c.try_into().expect("chunks_exact yields N-byte arrays")))
.collect()
}
#[cfg(feature = "compression")]
pub(crate) fn encode_be<const N: usize, T: Copy, F>(values: &[T], conv: F) -> Vec<u8>
where
F: Fn(T) -> [u8; N],
{
let mut out = Vec::new();
extend_be(&mut out, values, conv);
out
}
pub(crate) fn extend_be<const N: usize, T: Copy, F>(out: &mut Vec<u8>, values: &[T], conv: F)
where
F: Fn(T) -> [u8; N],
{
let start = out.len();
out.resize(start + values.len() * N, 0);
for (slot, &v) in out[start..].chunks_exact_mut(N).zip(values) {
slot.copy_from_slice(&conv(v));
}
}
pub(crate) fn push_pq_descriptor(out: &mut Vec<u8>, wide: bool, count: u64, offset: u64) {
if wide {
out.extend_from_slice(&(count as i64).to_be_bytes());
out.extend_from_slice(&(offset as i64).to_be_bytes());
} else {
out.extend_from_slice(&(count as i32).to_be_bytes());
out.extend_from_slice(&(offset as i32).to_be_bytes());
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decode_and_encode_are_inverse_and_big_endian() {
assert_eq!(
decode_be(&[0x00, 0x01, 0xFF, 0xFF], i16::from_be_bytes),
vec![1i16, -1]
);
let mut enc = Vec::new();
extend_be(&mut enc, &[1i16, -1], i16::to_be_bytes);
assert_eq!(enc, vec![0, 1, 0xFF, 0xFF]);
let mut out = vec![0xAAu8];
extend_be(&mut out, &[256i32], i32::to_be_bytes);
assert_eq!(out, vec![0xAA, 0, 0, 1, 0]);
}
}