use std::borrow::Cow;
use nom::error::FromExternalError;
use thiserror::Error;
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum ErrorKind {
MalformedInteger,
MalformedFloat,
MalformedHex,
MalformedText,
MalformedBase64,
Unparseable,
}
#[derive(Debug, Error)]
#[error("{kind:?}({ctx})")]
pub struct ParseError {
pub kind: ErrorKind,
pub ctx: String,
}
impl From<CowParseError<'_>> for ParseError {
fn from(err: CowParseError<'_>) -> Self {
ParseError {
kind: err.kind,
ctx: err.ctx.into(),
}
}
}
#[derive(Debug, PartialEq)]
pub(crate) struct CowParseError<'a> {
pub kind: ErrorKind,
pub ctx: Cow<'a, str>,
}
impl<I, E> FromExternalError<I, E> for CowParseError<'_> {
fn from_external_error(_input: I, _kind: nom::error::ErrorKind, _e: E) -> Self {
CowParseError {
kind: ErrorKind::Unparseable,
ctx: "nom-error".into(),
}
}
}
pub(crate) fn parse_error<'a, S: Into<Cow<'a, str>>>(kind: ErrorKind, ctx: S) -> CowParseError<'a> {
CowParseError {
kind,
ctx: ctx.into(),
}
}
impl From<nom::Err<CowParseError<'_>>> for ParseError {
fn from(e: nom::Err<CowParseError>) -> ParseError {
match e {
nom::Err::Incomplete(_) => parse_error(ErrorKind::Unparseable, "Incomplete"),
nom::Err::Error(pe) => pe,
nom::Err::Failure(pe) => pe,
}
.into()
}
}
impl<'a, I: Into<Cow<'a, str>>> nom::error::ParseError<I> for CowParseError<'a> {
fn from_error_kind(input: I, _kind: nom::error::ErrorKind) -> Self {
parse_error(ErrorKind::Unparseable, input)
}
fn append(_input: I, _kind: nom::error::ErrorKind, other: Self) -> Self {
other
}
}