Skip to main content

sark_core/utils/
bytes.rs

1pub struct Word;
2
3impl Word {
4    pub fn swar_eq_ci<const N: usize>(haystack: &[u8], expected: &[u8; N]) -> bool {
5        let Some(h) = haystack.first_chunk::<N>() else {
6            return false;
7        };
8        const M64: u64 = u64::from_le_bytes([0x20; 8]);
9        const M32: u32 = u32::from_le_bytes([0x20; 4]);
10        const M16: u16 = u16::from_le_bytes([0x20; 2]);
11        let mut i = 0usize;
12        while i + 8 <= N {
13            let raw = u64::from_le_bytes(h[i..i + 8].try_into().unwrap()) | M64;
14            let exp = u64::from_le_bytes(expected[i..i + 8].try_into().unwrap());
15            if raw != exp {
16                return false;
17            }
18            i += 8;
19        }
20        if i + 4 <= N {
21            let raw = u32::from_le_bytes(h[i..i + 4].try_into().unwrap()) | M32;
22            let exp = u32::from_le_bytes(expected[i..i + 4].try_into().unwrap());
23            if raw != exp {
24                return false;
25            }
26            i += 4;
27        }
28        if i + 2 <= N {
29            let raw = u16::from_le_bytes(h[i..i + 2].try_into().unwrap()) | M16;
30            let exp = u16::from_le_bytes(expected[i..i + 2].try_into().unwrap());
31            if raw != exp {
32                return false;
33            }
34            i += 2;
35        }
36        if i < N && h[i] | 0x20 != expected[i] {
37            return false;
38        }
39        true
40    }
41}
42
43pub struct Ascii;
44
45impl Ascii {
46    #[inline(always)]
47    pub fn fold_usize(mut acc: usize, chunk: &[u8]) -> Option<usize> {
48        for &b in chunk {
49            if !b.is_ascii_digit() {
50                return None;
51            }
52            acc = acc.checked_mul(10)?.checked_add((b - b'0') as usize)?;
53        }
54        Some(acc)
55    }
56
57    #[inline(always)]
58    pub fn fold_u64(mut acc: u64, chunk: &[u8]) -> Option<u64> {
59        for &b in chunk {
60            if !b.is_ascii_digit() {
61                return None;
62            }
63            acc = acc.checked_mul(10)?.checked_add((b - b'0') as u64)?;
64        }
65        Some(acc)
66    }
67
68    #[inline(always)]
69    pub fn parse_usize(bytes: &[u8]) -> Option<usize> {
70        if bytes.is_empty() {
71            return None;
72        }
73        Self::fold_usize(0, bytes)
74    }
75
76    #[inline(always)]
77    pub fn parse_u64(bytes: &[u8]) -> Option<u64> {
78        if bytes.is_empty() {
79            return None;
80        }
81        Self::fold_u64(0, bytes)
82    }
83}