1//! Common utilities, for internal use only.
23/// Helper methods to process immutable bytes.
4pub(crate) trait ByteSlice {
5/// Read 8 bytes as a 64-bit integer in little-endian order.
6fn read_u64le(&self) -> u64;
78/// Write a 64-bit integer as 8 bytes in little-endian order.
9fn write_u64le(&mut self, value: u64);
1011/// Calculate the offset of a slice from another.
12fn offset_from(&self, other: &Self) -> isize;
1314/// Iteratively parse and consume digits from bytes.
15 /// Returns the same bytes with consumed digits being
16 /// elided.
17#[allow(clippy::impl_trait_in_params)] // clippy bug: should not warn method of private trait
18fn parse_digits(&self, func: impl FnMut(u8)) -> &Self;
19}
2021impl ByteSlice for [u8] {
22#[inline(always)] // inlining this is crucial to remove bound checks
23fn read_u64le(&self) -> u64 {
24 u64::from_le_bytes(self[..8].try_into().unwrap())
25 }
2627#[inline(always)] // inlining this is crucial to remove bound checks
28fn write_u64le(&mut self, value: u64) {
29self[..8].copy_from_slice(&value.to_le_bytes());
30 }
3132#[inline]
33fn offset_from(&self, other: &Self) -> isize {
34 other.len() as isize - self.len() as isize
35 }
3637#[inline]
38fn parse_digits(&self, mut func: impl FnMut(u8)) -> &Self {
39let mut s = self;
4041// FIXME: Can't use s.split_first() here yet,
42 // see https://github.com/rust-lang/rust/issues/109328
43 // (fixed in LLVM 17)
44while let [c, s_next @ ..] = s {
45let c = c.wrapping_sub(b'0');
46if c < 10 {
47 func(c);
48 s = s_next;
49 } else {
50break;
51 }
52 }
5354 s
55 }
56}
5758/// Determine if 8 bytes are all decimal digits.
59/// This does not care about the order in which the bytes were loaded.
60pub(crate) const fn is_8digits(v: u64) -> bool {
61let a = v.wrapping_add(0x4646_4646_4646_4646);
62let b = v.wrapping_sub(0x3030_3030_3030_3030);
63 (a | b) & 0x8080_8080_8080_8080 == 0
64}
6566/// A custom 64-bit floating point type, representing `f * 2^e`.
67/// e is biased, so it be directly shifted into the exponent bits.
68#[derive(Copy, Clone, PartialEq, Eq, Default)]
69pub(crate) struct BiasedFp {
70/// The significant digits.
71pub(crate) f: u64,
72/// The biased, binary exponent.
73pub(crate) e: i32,
74}
7576impl BiasedFp {
77#[inline]
78pub(crate) const fn zero_pow2(e: i32) -> Self {
79Self { f: 0, e }
80 }
81}