rocket_http_community/parse/uri/
error.rs

1use std::borrow::Cow;
2use std::{convert, fmt};
3
4use crate::ext::IntoOwned;
5use crate::parse::uri::RawInput;
6use pear::error::Expected;
7use pear::input::ParseError;
8
9/// Error emitted on URI parse failure.
10///
11/// Internally, the type includes information about where the parse error
12/// occurred (the error's context) and information about what went wrong.
13/// Externally, this information can be retrieved (in textual form) through its
14/// `Display` implementation. In other words, by printing a value of this type.
15#[derive(Debug)]
16pub struct Error<'a> {
17    pub(crate) expected: Expected<u8, Cow<'a, [u8]>>,
18    pub(crate) index: usize,
19}
20
21#[doc(hidden)]
22impl<'a> From<ParseError<RawInput<'a>>> for Error<'a> {
23    fn from(inner: ParseError<RawInput<'a>>) -> Self {
24        let expected = inner.error.map(convert::identity, |v| v.values.into());
25        Error {
26            expected,
27            index: inner.info.context.start,
28        }
29    }
30}
31
32impl Error<'_> {
33    /// Returns the byte index into the text where the error occurred if it is
34    /// known.
35    ///
36    /// # Example
37    ///
38    /// ```rust
39    /// # extern crate rocket;
40    /// use rocket::http::uri::Origin;
41    ///
42    /// let err = Origin::parse("/foo bar").unwrap_err();
43    /// assert_eq!(err.index(), 4);
44    /// ```
45    pub fn index(&self) -> usize {
46        self.index
47    }
48}
49
50impl fmt::Display for Error<'_> {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "{} at index {}", self.expected, self.index)
53    }
54}
55
56impl IntoOwned for Error<'_> {
57    type Owned = Error<'static>;
58
59    fn into_owned(self) -> Error<'static> {
60        Error {
61            expected: self.expected.map(|t| t, |s| s.into_owned().into()),
62            index: self.index,
63        }
64    }
65}
66
67impl std::error::Error for Error<'_> {}
68
69#[cfg(test)]
70mod tests {
71    use crate::parse::uri::origin_from_str;
72
73    macro_rules! check_err {
74        ($url:expr => $error:expr) => {{
75            let e = origin_from_str($url).unwrap_err();
76            assert_eq!(e.to_string(), $error.to_string())
77        }};
78    }
79
80    #[test]
81    fn check_display() {
82        check_err!("a" => "expected token '/' but found 'a' at index 0");
83        check_err!("?" => "expected token '/' but found '?' at index 0");
84        check_err!("θΏ™" => "expected token '/' but found byte 232 at index 0");
85    }
86}