1#![cfg_attr(feature = "nightly", feature(specialization))]
2
3mod iter;
4mod reader;
5
6pub use frunk_core::hlist;
7pub use iter::{IntoParserIter, ParserIter};
8pub use reader::{Reader, ReaderBuild, ReaderBuildIter, ReaderRead};
9
10use std::{
11 fmt,
12 io::{self, Read, Seek},
13};
14
15#[derive(Debug, PartialEq, Eq)]
16pub enum Error<E> {
17 Error { error: E, offset: Option<u64> },
18 Eof,
19}
20
21impl<E: fmt::Display> fmt::Display for Error<E> {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 match self {
24 Error::Error { error, offset } => {
25 if let Some(o) = offset {
26 write!(f, "@{}: {}", o, error)
27 } else {
28 write!(f, "@???: {}", error)
29 }
30 }
31 Error::Eof => write!(f, "@eof"),
32 }
33 }
34}
35
36impl<E> Error<E> {
37 pub fn new<I: Into<E>>(error: I, offset: Option<u64>) -> Self {
38 Error::Error {
39 error: error.into(),
40 offset,
41 }
42 }
43}
44
45pub trait MaybePosition {
48 fn position(&mut self) -> Option<u64>;
49}
50
51#[cfg(feature = "nightly")]
52impl<T> MaybePosition for T {
53 default fn position(&mut self) -> Option<u64> {
54 None
55 }
56}
57
58impl<T: Seek> MaybePosition for T {
59 fn position(&mut self) -> Option<u64> {
60 self.seek(std::io::SeekFrom::Current(0)).ok()
61 }
62}
63
64pub type ParseResult<T, N, E> = Result<(T, N), E>;
65
66pub struct JustResult<T, E> {
67 inner: Result<T, E>,
68}
69
70impl<T, E> JustResult<T, E> {
71 pub fn new(inner: Result<T, E>) -> Self {
72 JustResult { inner }
73 }
74}
75
76impl<T, E> Parser for JustResult<T, E> {
77 type Item = T;
78 type Next = ();
79 type Error = Error<E>;
80
81 fn next<R: Read>(self, _reader: &mut R) -> ParseResult<Self::Item, Self::Next, Self::Error> {
82 #[cfg(feature = "nightly")]
83 {
84 self.inner
85 .map(|v| (v, ()))
86 .map_err(|e| Error::new(e, _reader.position()))
87 }
88 #[cfg(not(feature = "nightly"))]
89 {
90 self.inner.map(|v| (v, ())).map_err(|e| Error::new(e, None))
91 }
92 }
93}
94
95pub trait ParseOne: Parser<Next = ()> {
96 fn parse<R: Read>(self, reader: &mut R) -> Result<Self::Item, Self::Error>;
97}
98
99impl<T> ParseOne for T
100where
101 T: Parser<Next = ()>,
102{
103 fn parse<R: Read>(self, reader: &mut R) -> Result<Self::Item, Self::Error> {
104 Parser::next(self, reader).map(|(v, ())| v)
105 }
106}
107
108pub trait IntoParser {
109 type Item;
110 type Next;
111 type Error;
112 type Parser: Parser<Item = Self::Item, Next = Self::Next, Error = Self::Error>;
113
114 fn into(self) -> Self::Parser;
115}
116
117impl<T> IntoParser for T
118where
119 T: Parser,
120{
121 type Item = <Self as Parser>::Item;
122 type Next = <Self as Parser>::Next;
123 type Error = <Self as Parser>::Error;
124 type Parser = Self;
125
126 fn into(self) -> Self::Parser {
127 self
128 }
129}
130
131impl<T, E> IntoParser for Result<T, E> {
132 type Item = T;
133 type Next = ();
134 type Error = Error<E>;
135 type Parser = JustResult<T, E>;
136
137 fn into(self) -> Self::Parser {
138 JustResult { inner: self }
139 }
140}
141
142pub trait Parser {
143 type Item;
144 type Next;
145 type Error;
146
147 fn next<R: Read>(self, reader: &mut R) -> ParseResult<Self::Item, Self::Next, Self::Error>;
148}
149
150macro_rules! tuple_parser {
151 () => {};
152 ($first:ident $(, $rest:ident)*) => {
153 #[allow(unused_parens)]
154 impl<$first, $($rest,)*> Parser for ((), $first, $($rest,)*)
155 where
156 ($first $(, $rest)*): Parser
157 {
158 type Item = <($first $(, $rest)*) as Parser>::Item;
159 type Next = <($first $(, $rest)*) as Parser>::Next;
160 type Error = <($first $(, $rest)*) as Parser>::Error;
161
162 #[allow(non_snake_case)]
163 fn next<R: Read>(self, reader: &mut R) -> ParseResult<Self::Item, Self::Next, Self::Error> {
164 let ((), $first, $($rest,)*) = self;
165 ($first $(, $rest)*).next(reader)
166 }
167 }
168
169 impl<$first: Parser, $($rest: Parser<Error = $first::Error>,)*> Parser for ($first, $($rest,)*) {
170 type Item = $first::Item;
171 type Next = ($first::Next, $($rest,)*);
172 type Error = $first::Error;
173
174 #[allow(non_snake_case)]
175 fn next<R: Read>(self, reader: &mut R) -> ParseResult<Self::Item, Self::Next, Self::Error> {
176 let ($first, $($rest,)*) = self;
177 $first.next(reader).map(move |(i, n)| (i, (n, $($rest,)*)))
178 }
179 }
180
181 tuple_parser!($($rest),*);
182 }
183}
184
185tuple_parser!(A, B, C, D, E, F, G, H);
186
187pub trait CollectHelper<E> {
188 type Item;
189
190 fn collect<R: Read>(self, reader: &mut R) -> Result<Self::Item, E>;
191}
192
193impl<E> CollectHelper<E> for () {
194 type Item = ();
195
196 fn collect<R: Read>(self, _reader: &mut R) -> Result<Self::Item, E> {
197 Ok(())
198 }
199}
200
201fn make_eof_unexpected<T, E>(r: Result<T, Error<E>>, pos: Option<u64>) -> Result<T, Error<E>>
202where
203 E: From<io::Error>,
204{
205 match r {
206 Err(Error::Eof) => Err(Error::Error {
207 error: io::Error::from(io::ErrorKind::UnexpectedEof).into(),
208 offset: pos,
209 }),
210 other => other,
211 }
212}
213
214impl<P, E> CollectHelper<P::Error> for P
215where
216 P: Parser<Error = Error<E>>,
217 P::Next: CollectHelper<P::Error>,
218 E: From<io::Error>,
219{
220 type Item = (P::Item, <P::Next as CollectHelper<P::Error>>::Item);
221
222 fn collect<R: Read>(self, reader: &mut R) -> Result<Self::Item, P::Error> {
223 let (cur, next) = self.next(reader)?;
224
225 #[cfg(not(feature = "nightly"))]
226 let pos = None;
227 #[cfg(feature = "nightly")]
228 let pos = reader.position();
229
230 let rest = make_eof_unexpected(next.collect(reader), pos)?;
233
234 Ok((cur, rest))
235 }
236}