use nom::error::{Error as NomError, ErrorKind};
use std::error::Error;
use std::fmt::{Debug, Display};
use std::str::Utf8Error;
#[derive(Debug)]
pub enum ParseError {
Other {
at: ErrorBytes,
kind: ErrorKind,
},
Incomplete,
Utf8Error { bytes: Vec<u8>, source: Utf8Error },
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::Other { at, kind } => {
write!(f, "Error parings input: {} at {at}", kind.description())
}
ParseError::Incomplete => write!(f, "Incomplete input"),
ParseError::Utf8Error { source, .. } => Display::fmt(&source, f),
}
}
}
impl Error for ParseError {}
#[derive(Debug)]
pub enum ErrorBytes {
Valid(String),
Invalid(Vec<u8>),
}
impl Display for ErrorBytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ErrorBytes::Valid(str) => Display::fmt(&str, f),
ErrorBytes::Invalid(bytes) => Debug::fmt(&bytes, f),
}
}
}
impl Error for ErrorBytes {}
impl From<nom::Err<NomError<&[u8]>>> for ParseError {
fn from(e: nom::Err<NomError<&[u8]>>) -> Self {
match e {
nom::Err::Error(NomError { input, code })
| nom::Err::Failure(NomError { input, code }) => {
match std::str::from_utf8(input) {
Ok(s) => ParseError::Other {
at: ErrorBytes::Valid(s.to_owned()),
kind: code,
},
Err(_) => ParseError::Other {
at: ErrorBytes::Invalid(input.to_vec()),
kind: code,
},
}
}
nom::Err::Incomplete(_) => ParseError::Incomplete,
}
}
}