use nom::error::{Error as NomError, ErrorKind};
use std::str::Utf8Error;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, ParseError>;
#[derive(Debug, Error)]
pub enum ParseError {
#[error("Error parings input: {} at {at}", .kind.description())]
Other {
at: ErrorBytes,
kind: ErrorKind,
},
#[error("Incomplete input")]
Incomplete,
#[error("Error parsing string to utf8")]
Utf8Error { bytes: Vec<u8>, source: Utf8Error },
#[error(transparent)]
TransUtf8Error(#[from] std::str::Utf8Error),
}
#[derive(Debug, Error)]
pub enum ErrorBytes {
#[error("`{0}`")]
Valid(String),
#[error("`{0:?}`")]
Invalid(Vec<u8>),
}
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,
}
}
}