1use crate::{
3 take_while, Incomplete, InvalidRepetition, LenBytes, MapExt, Pipe, Repetition, Tag,
4 TakeAtom,
5};
6use fatal_error::FatalError;
7use std::error::Error as StdError;
8
9impl LenBytes for u8 {
10 fn len_bytes(&self) -> usize { 1 }
11}
12
13pub struct ByteAtom<'a>(&'a [u8], usize);
15
16impl<'a> From<&'a [u8]> for ByteAtom<'a> {
17 fn from(value: &'a [u8]) -> Self { ByteAtom(value, 0) }
18}
19
20impl<'a> TakeAtom for ByteAtom<'a> {
21 type Atom = u8;
22 type Container = &'a [u8];
23
24 fn next(&mut self) -> Option<(usize, Self::Atom)> {
25 if let x @ Some(_) = self.0.get(self.1).map(|x| (self.1, *x)) {
26 self.1 += 1;
27 x
28 } else {
29 None
30 }
31 }
32
33 fn split_at(self, index: usize) -> (Self::Container, Self::Container) {
34 (&self.0[index..], &self.0[..index])
35 }
36}
37
38pub struct ConstByteAtom<'a, const N: usize>(&'a [u8; N], usize);
40
41impl<'a, const N: usize> From<&'a [u8; N]> for ConstByteAtom<'a, N> {
42 fn from(value: &'a [u8; N]) -> Self { ConstByteAtom(value, 0) }
43}
44
45impl<'a, const N: usize> TakeAtom for ConstByteAtom<'a, N> {
46 type Atom = u8;
47 type Container = &'a [u8];
48
49 fn next(&mut self) -> Option<(usize, Self::Atom)> {
50 if self.1 < N {
51 let r = Some((self.1, self.0[self.1]));
52 self.1 += 1;
53 r
54 } else {
55 None
56 }
57 }
58
59 fn split_at(self, index: usize) -> (Self::Container, Self::Container) {
60 (&self.0[index..], &self.0[..index])
61 }
62}
63
64#[inline]
68pub fn ascii_digits<'a, E>(
69 qty: impl TryInto<Repetition, Error = impl Into<InvalidRepetition>>,
70) -> impl Pipe<&'a [u8], (&'a [u8],), E>
71where
72 Incomplete: Into<E>,
73{
74 let qty = qty.try_into().map_err(Into::into).unwrap();
75 move |i: &'a [u8]| {
76 take_while(|x: u8| x.is_ascii_digit(), qty).apply(ByteAtom::from(i))
77 }
78}
79
80#[inline]
82pub fn take<'a, E>(n: usize) -> impl Pipe<&'a [u8], (&'a [u8],), E>
83where
84 Incomplete: Into<E>,
85{
86 #[inline]
87 move |x: &'a [u8]| {
88 if x.len() >= n {
89 Ok((&x[n..], (&x[..n],)))
90 } else {
91 Err(FatalError::Error(Incomplete::Size(n - x.len()).into()))
92 }
93 }
94}
95
96#[inline]
98pub fn const_take<'a, const N: usize, E>() -> impl Pipe<&'a [u8], ([u8; N],), E>
99where
100 Incomplete: Into<E>,
101{
102 #[inline]
103 move |x: &'a [u8]| {
104 if x.len() >= N {
105 Ok((
106 &x[N..],
107 (if let Ok(x) = x[..N].try_into() { x } else { unreachable!() },),
108 ))
109 } else {
110 Err(FatalError::Error(Incomplete::Size(N - x.len()).into()))
111 }
112 }
113}
114
115#[inline]
117pub fn be_u8<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u8,), E>
118where
119 Incomplete: Into<E>,
120{
121 const_take::<1, E>().map(|x: [u8; 1]| (u8::from_be_bytes(x),))
122}
123
124#[inline]
126pub fn be_u16<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u16,), E>
127where
128 Incomplete: Into<E>,
129{
130 const_take::<2, E>().map(|x: [u8; 2]| (u16::from_be_bytes(x),))
131}
132
133#[inline]
135pub fn be_u32<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u32,), E>
136where
137 Incomplete: Into<E>,
138{
139 const_take::<4, E>().map(|x: [u8; 4]| (u32::from_be_bytes(x),))
140}
141
142#[inline]
144pub fn be_u64<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u64,), E>
145where
146 Incomplete: Into<E>,
147{
148 const_take::<8, E>().map(|x: [u8; 8]| (u64::from_be_bytes(x),))
149}
150
151#[inline]
153pub fn le_u8<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u8,), E>
154where
155 Incomplete: Into<E>,
156{
157 const_take::<1, E>().map(|x: [u8; 1]| (u8::from_le_bytes(x),))
158}
159
160#[inline]
162pub fn le_u16<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u16,), E>
163where
164 Incomplete: Into<E>,
165{
166 const_take::<2, E>().map(|x: [u8; 2]| (u16::from_le_bytes(x),))
167}
168
169#[inline]
171pub fn le_u32<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u32,), E>
172where
173 Incomplete: Into<E>,
174{
175 const_take::<4, E>().map(|x: [u8; 4]| (u32::from_le_bytes(x),))
176}
177
178#[inline]
180pub fn le_u64<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (u64,), E>
181where
182 Incomplete: Into<E>,
183{
184 const_take::<8, E>().map(|x: [u8; 8]| (u64::from_le_bytes(x),))
185}
186
187#[inline]
189pub fn be_i8<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i8,), E>
190where
191 Incomplete: Into<E>,
192{
193 const_take::<1, E>().map(|x: [u8; 1]| (i8::from_be_bytes(x),))
194}
195
196#[inline]
198pub fn be_i16<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i16,), E>
199where
200 Incomplete: Into<E>,
201{
202 const_take::<2, E>().map(|x: [u8; 2]| (i16::from_be_bytes(x),))
203}
204
205#[inline]
207pub fn be_i32<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i32,), E>
208where
209 Incomplete: Into<E>,
210{
211 const_take::<4, E>().map(|x: [u8; 4]| (i32::from_be_bytes(x),))
212}
213
214#[inline]
216pub fn be_i64<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i64,), E>
217where
218 Incomplete: Into<E>,
219{
220 const_take::<8, E>().map(|x: [u8; 8]| (i64::from_be_bytes(x),))
221}
222
223#[inline]
225pub fn le_i8<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i8,), E>
226where
227 Incomplete: Into<E>,
228{
229 const_take::<1, E>().map(|x: [u8; 1]| (i8::from_le_bytes(x),))
230}
231
232#[inline]
234pub fn le_i16<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i16,), E>
235where
236 Incomplete: Into<E>,
237{
238 const_take::<2, E>().map(|x: [u8; 2]| (i16::from_le_bytes(x),))
239}
240
241#[inline]
243pub fn le_i32<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i32,), E>
244where
245 Incomplete: Into<E>,
246{
247 const_take::<4, E>().map(|x: [u8; 4]| (i32::from_le_bytes(x),))
248}
249
250#[inline]
252pub fn le_i64<'a, E: StdError + 'static>() -> impl Pipe<&'a [u8], (i64,), E>
253where
254 Incomplete: Into<E>,
255{
256 const_take::<8, E>().map(|x: [u8; 8]| (i64::from_le_bytes(x),))
257}
258
259#[derive(Debug, Clone, PartialEq, Eq)]
261pub struct TagBytesError(pub Vec<u8>, pub Vec<u8>);
262
263impl std::fmt::Display for TagBytesError {
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 write!(f, "expected: '{:?}' got: '{:?}'", self.0, self.1)
266 }
267}
268
269impl std::error::Error for TagBytesError {}
270
271impl<'a, 'b, E> Tag<&'a [u8], E> for &'b [u8]
272where
273 E: StdError,
274 TagBytesError: Into<E>,
275 Incomplete: Into<E>,
276{
277 type Output = &'a [u8];
278
279 fn strip_from(&self, input: &'a [u8]) -> Result<(&'a [u8], (Self::Output,)), E> {
280 if let Some(x) = input.strip_prefix(*self) {
281 Ok((x, (&input[..self.len()],)))
282 } else {
283 Err(if self.starts_with(input) {
284 Incomplete::Size(self.len() - input.len()).into()
285 } else {
286 let end = if input.len() < self.len() { input.len() } else { self.len() };
287 TagBytesError(self.to_vec(), input[..end].to_vec()).into()
288 })
289 }
290 }
291}
292
293impl<'a, 'b, E, const N: usize> Tag<&'a [u8], E> for &'b [u8; N]
294where
295 E: StdError,
296 Incomplete: Into<E>,
297 TagBytesError: Into<E>,
298{
299 type Output = &'a [u8];
300
301 fn strip_from(&self, input: &'a [u8]) -> Result<(&'a [u8], (Self::Output,)), E> {
302 if let Some(x) = input.strip_prefix(*self) {
303 Ok((x, (&input[..self.len()],)))
304 } else {
305 Err(if self.starts_with(input) {
306 Incomplete::Size(N - input.len()).into()
307 } else {
308 let end = if input.len() < N { input.len() } else { N };
309 TagBytesError(self.to_vec(), input[..end].to_vec()).into()
310 })
311 }
312 }
313}
314
315#[derive(Debug, Clone, PartialEq, Eq)]
317pub struct TagByteError(pub u8, pub u8);
318
319impl std::fmt::Display for TagByteError {
320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321 write!(f, "Expected: '{}' got: '{}'", self.0, self.1)
322 }
323}
324
325impl std::error::Error for TagByteError {}
326
327impl<'a, E> Tag<&'a [u8], E> for u8
328where
329 E: StdError,
330 Incomplete: Into<E>,
331 TagByteError: Into<E>,
332{
333 type Output = u8;
334
335 fn strip_from(&self, input: &'a [u8]) -> Result<(&'a [u8], (Self::Output,)), E> {
336 if let Some(x) = input.strip_prefix(&[*self]) {
337 Ok((x, (*self,)))
338 } else {
339 Err(if input.is_empty() {
340 Incomplete::Size(1).into()
341 } else {
342 TagByteError(*self, input[0]).into()
343 })
344 }
345 }
346}
347
348pub fn consumed<'a, O, E>(
379 mut p: impl Pipe<&'a [u8], O, E>,
380) -> impl Pipe<&'a [u8], (&'a [u8],), E> {
381 move |x: &'a [u8]| {
382 let (i, _) = p.apply(x)?;
383 Ok((i, (&x[..x.len() - i.len()],)))
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::TagByteError;
390 use crate::{
391 byte::{ascii_digits, take, TagBytesError},
392 tag, Incomplete, Pipe,
393 };
394 use fatal_error::FatalError;
395
396 #[derive(Debug, PartialEq, Eq)]
397 enum Error {
398 Incomplete(Incomplete),
399 TagByte(TagByteError),
400 TagBytes(TagBytesError),
401 }
402
403 impl std::fmt::Display for Error {
404 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
405 write!(f, "{self:?}")
406 }
407 }
408
409 impl From<Incomplete> for Error {
410 fn from(value: Incomplete) -> Self { Error::Incomplete(value) }
411 }
412
413 impl From<TagByteError> for Error {
414 fn from(value: TagByteError) -> Self { Error::TagByte(value) }
415 }
416
417 impl From<TagBytesError> for Error {
418 fn from(value: TagBytesError) -> Self { Error::TagBytes(value) }
419 }
420
421 impl std::error::Error for Error {}
422
423 #[test]
424 fn test_tag() {
425 assert_eq!(
426 tag::<Error, _, _>(b"foo").apply(b"fooo"),
427 Ok((&b"o"[..], (&b"foo"[..],)))
428 );
429 assert_eq!(
430 tag::<Error, _, _>(b"foo").apply(b"fo"),
431 Err(FatalError::Error(Error::Incomplete(Incomplete::Size(1))))
432 );
433 assert_eq!(
434 tag::<Error, _, _>(b"foo").apply(b"faaa"),
435 Err(FatalError::Error(
436 TagBytesError(b"foo".to_vec(), b"faa".to_vec()).into(),
437 ))
438 );
439 }
440
441 #[test]
442 fn test_take() {
443 assert_eq!(take::<Incomplete>(1).apply(b"yolo"), Ok((&b"olo"[..], (&b"y"[..],))));
444 assert_eq!(
445 take::<Incomplete>(8).apply(b"yolo"),
446 Err(FatalError::Error(Incomplete::Size(4)))
447 );
448 }
449
450 #[derive(Debug, PartialEq, Eq)]
451 enum AsciiiDigitErr {
452 Incomplete(Incomplete),
453 }
454
455 impl From<Incomplete> for AsciiiDigitErr {
456 fn from(value: Incomplete) -> Self { AsciiiDigitErr::Incomplete(value) }
457 }
458
459 #[test]
460 fn test_digits() {
461 assert_eq!(
462 ascii_digits::<AsciiiDigitErr>(..).apply(b"0123"),
463 Ok((&b""[..], (&b"0123"[..],)))
464 );
465 assert_eq!(
466 ascii_digits::<AsciiiDigitErr>(..).apply(b""),
467 Ok((&b""[..], (&b""[..],)))
468 );
469 assert_eq!(
470 ascii_digits::<AsciiiDigitErr>(0..).apply(b""),
471 Ok((&b""[..], (&b""[..],)))
472 );
473 assert_eq!(
474 ascii_digits::<AsciiiDigitErr>(10..).apply(b""),
475 Err(FatalError::Error(Incomplete::Unknown.into()))
476 );
477 assert_eq!(
478 ascii_digits::<AsciiiDigitErr>(..=1).apply(b"012345"),
479 Ok((&b"12345"[..], (&b"0"[..],)))
480 );
481 assert_eq!(
482 ascii_digits::<AsciiiDigitErr>(..2).apply(b"012345"),
483 Ok((&b"12345"[..], (&b"0"[..],)))
484 );
485 assert_eq!(
486 ascii_digits::<AsciiiDigitErr>(2..3).apply(b"012345"),
487 Ok((&b"2345"[..], (&b"01"[..],)))
488 );
489 assert_eq!(
490 ascii_digits::<AsciiiDigitErr>(2..=2).apply(b"012345"),
491 Ok((&b"2345"[..], (&b"01"[..],)))
492 );
493 assert_eq!(
494 ascii_digits::<AsciiiDigitErr>(2..=3).apply(b"012345"),
495 Ok((&b"345"[..], (&b"012"[..],)))
496 );
497 assert_eq!(
498 ascii_digits::<AsciiiDigitErr>(2..=6).apply(b"012345abc"),
499 Ok((&b"abc"[..], (&b"012345"[..],)))
500 );
501 assert_eq!(
502 ascii_digits::<AsciiiDigitErr>(7..).apply(b"012345abc"),
503 Err(FatalError::Error(Incomplete::Unknown.into()))
504 );
505 }
506
507 #[test]
508 #[should_panic(
509 expected = "called `Result::unwrap()` on an `Err` value: InvalidRepetition(2, 1)"
510 )]
511 fn test_digits_invalid2() { ascii_digits::<AsciiiDigitErr>(2..2); }
512}