1use core::{mem, num::NonZero};
4
5const LANE: usize = 16;
6
7mod raw;
8
9#[derive(Clone, Copy)]
11pub struct Match<'a> {
12 bytes: &'a [u8],
13 end: NonZero<usize>,
14}
15
16impl<'a> Match<'a> {
17 pub fn find(byte: u8, bytes: &'a [u8]) -> Option<Self> {
18 let index = memchr::memchr(byte, bytes)?;
19 Some(unsafe { raw::found(bytes, index) })
21 }
22
23 pub fn find2(first: u8, second: u8, bytes: &'a [u8]) -> Option<Self> {
24 let index = memchr::memchr2(first, second, bytes)?;
25 Some(unsafe { raw::found(bytes, index) })
27 }
28
29 pub(crate) fn find_by(bytes: &'a [u8], mut matches: impl FnMut(u8) -> bool) -> Option<Self> {
30 let index = bytes.iter().position(|byte| matches(*byte))?;
31 Some(unsafe { raw::found(bytes, index) })
33 }
34
35 pub const fn start(self) -> usize {
36 self.end.get() - 1
37 }
38
39 pub const fn end(self) -> NonZero<usize> {
40 self.end
41 }
42
43 pub fn byte(self) -> u8 {
44 raw::byte(self)
45 }
46
47 pub fn prefix(self) -> &'a [u8] {
48 raw::before::<false>(self)
49 }
50
51 pub fn through(self) -> &'a [u8] {
52 raw::before::<true>(self)
53 }
54
55 pub fn tail(self) -> &'a [u8] {
56 raw::after::<true>(self)
57 }
58
59 pub fn suffix(self) -> &'a [u8] {
60 raw::after::<false>(self)
61 }
62}
63
64#[derive(PartialEq, Eq)]
65pub enum Outcome<T> {
66 Found(T),
67 Invalid { offset: usize, actual: u8 },
68 Partial,
69}
70
71#[repr(transparent)]
73pub struct Bytes<'a>(&'a [u8]);
74
75impl<'a> Bytes<'a> {
76 pub const fn new(bytes: &'a [u8]) -> Self {
77 Self(bytes)
78 }
79
80 pub fn name(&self, start: usize) -> Outcome<(usize, u8)> {
81 let Some(rest) = self.0.get(start..) else {
82 return Outcome::Partial;
83 };
84 let (prefix, rest) = rest.split_at(rest.len().min(LANE));
85 let outcome = name_tail(prefix, start);
86 if !matches!(outcome, Outcome::Partial) {
87 return outcome;
88 }
89 if rest.is_empty() {
90 return Outcome::Partial;
91 }
92 let index = start + prefix.len();
93 if rest.len() < LANE {
94 return name_tail(rest, index);
95 }
96 name_simd(rest, index)
97 }
98
99 pub fn value(&self, start: usize) -> Outcome<usize> {
100 let Some(rest) = self.0.get(start..) else {
101 return Outcome::Partial;
102 };
103 value_simd(rest, start)
104 }
105}
106
107fn name_simd(bytes: &[u8], mut index: usize) -> Outcome<(usize, u8)> {
108 let (lanes, tail) = bytes.as_chunks::<LANE>();
109 let (groups, lanes) = lanes.as_chunks::<4>();
110 for group in groups {
111 let [a, b, c, d] = group;
112 let masks = [
113 mask::<true>(*a),
114 mask::<true>(*b),
115 mask::<true>(*c),
116 mask::<true>(*d),
117 ];
118 let Some(found) = NonZero::new(packed(masks)) else {
119 index += 4 * LANE;
120 continue;
121 };
122 let (offset, byte) = first(group, found);
123 return name_at(index + offset, byte);
124 }
125 for lane in lanes {
126 let bits = mask::<true>(*lane);
127 if bits != 0 {
128 let (offset, byte) = in_lane(lane, bits);
129 return name_at(index + offset, byte);
130 }
131 index += LANE;
132 }
133 if tail.is_empty() {
134 Outcome::Partial
135 } else {
136 name_tail(tail, index)
137 }
138}
139
140fn value_simd(bytes: &[u8], mut index: usize) -> Outcome<usize> {
141 let Some((lane, rest)) = bytes.split_first_chunk::<LANE>() else {
142 return value_tail(bytes, index);
143 };
144 let bits = mask::<false>(*lane);
145 if bits != 0 {
146 let (offset, byte) = in_lane(lane, bits);
147 return value_at(bytes, offset, index + offset, byte);
148 }
149 index += LANE;
150 let (lanes, tail) = rest.as_chunks::<LANE>();
151 let (groups, lanes) = lanes.as_chunks::<4>();
152 let mut consumed = LANE;
153 for group in groups {
154 let [a, b, c, d] = group;
155 let masks = [
156 mask::<false>(*a),
157 mask::<false>(*b),
158 mask::<false>(*c),
159 mask::<false>(*d),
160 ];
161 let Some(found) = NonZero::new(packed(masks)) else {
162 index += 4 * LANE;
163 consumed += 4 * LANE;
164 continue;
165 };
166 let (offset, byte) = first(group, found);
167 return value_at(bytes, consumed + offset, index + offset, byte);
168 }
169 for lane in lanes {
170 let bits = mask::<false>(*lane);
171 if bits != 0 {
172 let (offset, byte) = in_lane(lane, bits);
173 return value_at(bytes, consumed + offset, index + offset, byte);
174 }
175 index += LANE;
176 consumed += LANE;
177 }
178 if tail.is_empty() {
179 Outcome::Partial
180 } else {
181 value_tail(tail, index)
182 }
183}
184
185fn name_tail(bytes: &[u8], index: usize) -> Outcome<(usize, u8)> {
186 for (offset, &byte) in bytes.iter().enumerate() {
187 let pos = index + offset;
188 if byte == b':' || byte == b'\r' {
189 return Outcome::Found((pos, byte));
190 }
191 if !crate::field::Error::is_name_byte(byte) {
192 return Outcome::Invalid {
193 offset: pos,
194 actual: byte,
195 };
196 }
197 }
198 Outcome::Partial
199}
200
201fn value_tail(bytes: &[u8], index: usize) -> Outcome<usize> {
202 for (offset, &byte) in bytes.iter().enumerate() {
203 if byte == b'\r' {
204 return value_at(bytes, offset, index + offset, byte);
205 }
206 if !crate::field::Error::is_text(byte) {
207 return Outcome::Invalid {
208 offset: index + offset,
209 actual: byte,
210 };
211 }
212 }
213 Outcome::Partial
214}
215
216fn in_lane(lane: &[u8; LANE], bits: u16) -> (usize, u8) {
221 let offset = bits.trailing_zeros() as usize & (LANE - 1);
222 (offset, lane[offset])
223}
224
225fn packed(masks: [u16; 4]) -> u64 {
227 let mut bits = 0;
228 for (lane, mask) in masks.into_iter().enumerate() {
229 bits |= u64::from(mask) << (lane * LANE);
230 }
231 bits
232}
233
234fn first(group: &[[u8; LANE]; 4], found: NonZero<u64>) -> (usize, u8) {
239 let ordinal = found.get().trailing_zeros() as usize;
240 (ordinal, group[ordinal / LANE][ordinal % LANE])
241}
242
243fn mask<const NAME: bool>(lane: [u8; LANE]) -> u16 {
244 let flags = lane.map(|byte| {
245 let invalid = if NAME {
246 !crate::field::Error::is_name_byte(byte)
247 } else {
248 !crate::field::Error::is_text(byte)
249 };
250 u8::from(invalid) << 7
251 });
252 let mut bits = 0;
253 for (index, chunk) in flags.as_chunks::<8>().0.iter().enumerate() {
255 let word = u64::from_le_bytes(*chunk);
256 bits |= ((word.wrapping_mul(0x0002_0408_1020_4081) >> 56) as u16) << (index * 8);
257 }
258 bits
259}
260
261fn name_at(pos: usize, byte: u8) -> Outcome<(usize, u8)> {
262 if byte == b':' || byte == b'\r' {
263 Outcome::Found((pos, byte))
264 } else {
265 Outcome::Invalid {
266 offset: pos,
267 actual: byte,
268 }
269 }
270}
271
272fn value_at(bytes: &[u8], offset: usize, pos: usize, byte: u8) -> Outcome<usize> {
273 if byte != b'\r' {
274 return Outcome::Invalid {
275 offset: pos,
276 actual: byte,
277 };
278 }
279 let Some(next) = bytes.get(offset + 1) else {
280 return Outcome::Partial;
281 };
282 if *next == b'\n' {
283 Outcome::Found(pos)
284 } else {
285 Outcome::Invalid {
286 offset: pos + 1,
287 actual: *next,
288 }
289 }
290}
291
292const _: () = {
293 let word = mem::size_of::<usize>();
294 assert!(mem::size_of::<Bytes<'_>>() == 2 * word);
295 assert!(mem::size_of::<Outcome<usize>>() == 2 * word);
296 assert!(mem::size_of::<Outcome<(usize, u8)>>() == 3 * word);
297 assert!(mem::size_of::<Match<'_>>() == 3 * word);
298 assert!(mem::size_of::<Option<Match<'_>>>() == 3 * word);
299};