1use std::fmt;
4use std::mem;
5
6use self::Error::*;
7use crate::lexer::{self, Lexer, Token};
8use crate::version::{Identifier, Version};
9
10#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
11pub enum Error<'input> {
12 UnexpectedEnd,
14 UnexpectedToken(Token<'input>),
16 Lexer(lexer::Error),
18 MoreInput(Vec<Token<'input>>),
20 EmptyPredicate,
22 EmptyRange,
24}
25
26impl<'input> From<lexer::Error> for Error<'input> {
27 fn from(value: lexer::Error) -> Self {
28 Error::Lexer(value)
29 }
30}
31
32impl<'input> fmt::Display for Error<'input> {
33 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
34 use self::Error::*;
35
36 match *self {
37 UnexpectedEnd => write!(fmt, "expected more input"),
38 UnexpectedToken(ref token) => write!(fmt, "encountered unexpected token: {:?}", token),
39 Lexer(ref error) => write!(fmt, "lexer error: {:?}", error),
40 MoreInput(ref tokens) => write!(fmt, "expected end of input, but got: {:?}", tokens),
41 EmptyPredicate => write!(fmt, "encountered empty predicate"),
42 EmptyRange => write!(fmt, "encountered empty range"),
43 }
44 }
45}
46
47impl<'input> From<Error<'input>> for String {
49 fn from(value: Error<'input>) -> Self {
50 value.to_string()
51 }
52}
53
54pub struct Parser<'input> {
56 lexer: Lexer<'input>,
58 c1: Option<Token<'input>>,
60}
61
62impl<'input> Parser<'input> {
63 pub fn new(input: &'input str) -> Result<Parser<'input>, Error<'input>> {
65 let mut lexer = Lexer::new(input);
66
67 let c1 = if let Some(c1) = lexer.next() {
68 Some(c1?)
69 } else {
70 None
71 };
72
73 Ok(Parser { lexer, c1 })
74 }
75
76 #[inline(always)]
78 fn pop(&mut self) -> Result<Token<'input>, Error<'input>> {
79 let c1 = if let Some(c1) = self.lexer.next() {
80 Some(c1?)
81 } else {
82 None
83 };
84
85 mem::replace(&mut self.c1, c1).ok_or_else(|| UnexpectedEnd)
86 }
87
88 #[inline(always)]
90 fn peek(&mut self) -> Option<&Token<'input>> {
91 self.c1.as_ref()
92 }
93
94 fn skip_whitespace(&mut self) -> Result<(), Error<'input>> {
96 match self.peek() {
97 Some(&Token::Whitespace(_, _)) => self.pop().map(|_| ()),
98 _ => Ok(()),
99 }
100 }
101
102 pub fn component(&mut self) -> Result<Option<u64>, Error<'input>> {
106 match self.pop()? {
107 Token::Numeric(number) => Ok(Some(number)),
108 ref t if t.is_wildcard() => Ok(None),
109 tok => Err(UnexpectedToken(tok)),
110 }
111 }
112
113 pub fn numeric(&mut self) -> Result<u64, Error<'input>> {
115 match self.pop()? {
116 Token::Numeric(number) => Ok(number),
117 tok => Err(UnexpectedToken(tok)),
118 }
119 }
120
121 pub fn dot_component(&mut self) -> Result<(Option<u64>, bool), Error<'input>> {
130 match self.peek() {
131 Some(&Token::Dot) => {}
132 _ => return Ok((None, false)),
133 }
134
135 self.pop()?;
137 self.component().map(|n| (n, n.is_none()))
138 }
139
140 pub fn dot_numeric(&mut self) -> Result<u64, Error<'input>> {
142 match self.pop()? {
143 Token::Dot => {}
144 tok => return Err(UnexpectedToken(tok)),
145 }
146
147 self.numeric()
148 }
149
150 pub fn identifier(&mut self) -> Result<Identifier, Error<'input>> {
154 self.bounded_identifier(0)
155 }
156
157 fn bounded_identifier(&mut self, count: u32) -> Result<Identifier, Error<'input>> {
158 if count > 255 {
159 panic!("Cannot have more than 255 identifiers");
160 }
161
162 let identifier = match self.pop()? {
163 Token::AlphaNumeric(identifier) => {
164 Identifier::AlphaNumeric(identifier.to_string())
166 }
167 Token::Numeric(n) => Identifier::Numeric(n),
168 tok => return Err(UnexpectedToken(tok)),
169 };
170
171 if let Some(&Token::Hyphen) = self.peek() {
172 self.pop()?;
174 Ok(identifier
176 .concat("-")
177 .concat(&self.bounded_identifier(count + 1)?.to_string()))
178 } else {
179 Ok(identifier)
180 }
181 }
182
183 fn pre(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
187 match self.peek() {
188 Some(&Token::Hyphen) => {}
189 _ => return Ok(vec![]),
190 }
191
192 self.pop()?;
194 self.parts()
195 }
196
197 fn parts(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
199 let mut parts = Vec::new();
200
201 parts.push(self.identifier()?);
202
203 while let Some(&Token::Dot) = self.peek() {
204 self.pop()?;
205
206 parts.push(self.identifier()?);
207 }
208
209 Ok(parts)
210 }
211
212 fn plus_build_metadata(&mut self) -> Result<Vec<Identifier>, Error<'input>> {
216 match self.peek() {
217 Some(&Token::Plus) => {}
218 _ => return Ok(vec![]),
219 }
220
221 self.pop()?;
223 self.parts()
224 }
225
226 pub fn version(&mut self) -> Result<Version, Error<'input>> {
230 self.skip_whitespace()?;
231
232 let major = self.numeric()?;
233 let minor = self.dot_numeric()?;
234 let patch = self.dot_numeric()?;
235 let pre = self.pre()?;
236 let build = self.plus_build_metadata()?;
237
238 self.skip_whitespace()?;
239
240 Ok(Version {
241 major,
242 minor,
243 patch,
244 pre,
245 build,
246 })
247 }
248
249 pub fn is_eof(&mut self) -> bool {
251 self.c1.is_none()
252 }
253
254 pub fn tail(&mut self) -> Result<Vec<Token<'input>>, Error<'input>> {
258 let mut out = Vec::new();
259
260 if let Some(t) = self.c1.take() {
261 out.push(t);
262 }
263
264 while let Some(t) = self.lexer.next() {
265 out.push(t?);
266 }
267
268 Ok(out)
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use crate::version::parse;
275
276 #[test]
277 #[should_panic(expected = "Cannot have more than 255 identifiers")]
278 fn fuzz_0001() {
279 let version = std::fs::read_to_string("tests/fixtures/fuzz-0001.txt").expect("should be able to read version from file");
280
281 parse(&version).ok();
282 }
283
284}