use std::{fmt, convert};
use std::borrow::Cow;
use pear::error::Expected;
use pear::input::ParseError;
use crate::parse::uri::RawInput;
use crate::ext::IntoOwned;
#[derive(Debug)]
pub struct Error<'a> {
pub(crate) expected: Expected<u8, Cow<'a, [u8]>>,
pub(crate) index: usize,
}
#[doc(hidden)]
impl<'a> From<ParseError<RawInput<'a>>> for Error<'a> {
fn from(inner: ParseError<RawInput<'a>>) -> Self {
let expected = inner.error.map(convert::identity, |v| v.values.into());
Error { expected, index: inner.info.context.start }
}
}
impl Error<'_> {
pub fn index(&self) -> usize {
self.index
}
}
impl fmt::Display for Error<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} at index {}", self.expected, self.index)
}
}
impl IntoOwned for Error<'_> {
type Owned = Error<'static>;
fn into_owned(self) -> Error<'static> {
Error {
expected: self.expected.map(|t| t, |s| s.into_owned().into()),
index: self.index
}
}
}
#[cfg(test)]
mod tests {
use crate::parse::uri::origin_from_str;
macro_rules! check_err {
($url:expr => $error:expr) => {{
let e = origin_from_str($url).unwrap_err();
assert_eq!(e.to_string(), $error.to_string())
}}
}
#[test]
fn check_display() {
check_err!("a" => "expected token '/' but found 'a' at index 0");
check_err!("?" => "expected token '/' but found '?' at index 0");
check_err!("这" => "expected token '/' but found byte 232 at index 0");
}
}