wiwi/
parser.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use crate::prelude_std::*;
use std::num::NonZero;

pub use input::{ Input, Needle };
pub use stateful::ParserStateful;
pub use stateless::Parser;

pub mod input;
pub mod stateful;
pub mod stateless;
pub mod util;

pub struct Success<I, O> {
	pub output: O,
	pub remaining_input: I,
}

#[derive(Debug)]
pub enum Error<E> {
	NotEnoughData { missing: Option<NonZero<usize>> },
	Error { error: E },
	Fatal { error: E }
}

pub type Result<I, O, E = ()> = std::result::Result<Success<I, O>, Error<E>>;

pub type ParserPhantom<I, O, E = ()> = PhantomData<ParserPhantomImpl<I, O, E>>;

/// This is an implementation detail of [`ParserPhantom`]
///
/// This helps to enforce the trait bounds of [`Parser`]/[`ParserStateful`] in
/// [`ParserPhantom`] type, to work around the fact that type aliases don't
/// enforce their trait bounds for now, which is a known rust type checker limitation.
#[doc(hidden)]
pub struct ParserPhantomImpl<I, O, E>
where
	I: Input
{
	__inner: fn(I) -> Result<I, O, E>
}

impl<E> Error<E> {
	#[inline]
	fn from<EFrom>(error: Error<EFrom>) -> Self
	where
		EFrom: Into<E>
	{
		use self::Error::*;

		match error {
			NotEnoughData { missing } => { NotEnoughData { missing } }
			Error { error } => { Error { error: error.into() } }
			Fatal { error } => { Fatal { error: error.into() } }
		}
	}

	#[inline]
	fn into<EInto>(self) -> Error<EInto>
	where
		E: Into<EInto>
	{
		Error::from(self)
	}
}

#[inline]
const fn max_init_cap<T>() -> usize {
	// 1 MiB
	const MAX_BYTES: usize = 1024 * 1024;

	if size_of::<T>() == 0 {
		// ZST, doesn't really matter honestly
		MAX_BYTES
	} else {
		MAX_BYTES / size_of::<T>()
	}
}