use std::num::{ParseFloatError, ParseIntError}; use nom::error::{ContextError, ErrorKind, FromExternalError, ParseError}; use thiserror::Error; #[cfg(doc)] use { crate::KdlNode, std::convert::{TryFrom, TryInto}, }; /// An error that occurs when parsing a KDL document. #[derive(Debug, Clone, Eq, PartialEq, Error)] #[error("Error parsing document at line {line} column {column}. {kind}")] pub struct KdlError { pub input: String, /// Offset in chars of the error. pub offset: usize, /// 1-based line number of the error. pub line: usize, /// 1-based column number (in chars) of the error. pub column: usize, pub kind: KdlErrorKind, } /// A type reprenting additional information specific to the type of error being returned. #[derive(Debug, Clone, Eq, PartialEq, Error)] pub enum KdlErrorKind { #[error(transparent)] ParseIntError(ParseIntError), #[error(transparent)] ParseFloatError(ParseFloatError), #[error("Failed to parse {0} component of semver string.")] Context(&'static str), #[error("An unspecified error occurred.")] Other, } /// Coversion errors for converting [`KdlNode`] to another type via [`TryFrom`] or [`TryInto`]. #[derive(Debug, Clone, Eq, PartialEq, Error)] #[error("Failed to convert from KdlNodeValue::{variant} to {expected}.")] pub struct TryFromKdlNodeValueError { pub(crate) expected: &'static str, pub(crate) variant: &'static str, } #[derive(Debug, Clone, Eq, PartialEq)] pub(crate) struct KdlParseError { pub(crate) input: I, pub(crate) context: Option<&'static str>, pub(crate) kind: Option, } impl ParseError for KdlParseError { fn from_error_kind(input: I, _kind: nom::error::ErrorKind) -> Self { Self { input, context: None, kind: None, } } fn append(_input: I, _kind: nom::error::ErrorKind, other: Self) -> Self { other } } impl ContextError for KdlParseError { fn add_context(_input: I, ctx: &'static str, mut other: Self) -> Self { other.context = Some(ctx); other } } impl<'a> FromExternalError<&'a str, ParseIntError> for KdlParseError<&'a str> { fn from_external_error(input: &'a str, _kind: ErrorKind, e: ParseIntError) -> Self { KdlParseError { input, context: None, kind: Some(KdlErrorKind::ParseIntError(e)), } } } impl<'a> FromExternalError<&'a str, ParseFloatError> for KdlParseError<&'a str> { fn from_external_error(input: &'a str, _kind: ErrorKind, e: ParseFloatError) -> Self { KdlParseError { input, context: None, kind: Some(KdlErrorKind::ParseFloatError(e)), } } }