use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseError {
pub(crate) message: String,
pub(crate) line: Option<u32>,
pub(crate) column: Option<u32>,
}
impl ParseError {
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
line: None,
column: None,
}
}
pub fn with_location(message: impl Into<String>, line: u32, column: u32) -> Self {
Self {
message: message.into(),
line: Some(line),
column: Some(column),
}
}
pub fn message(&self) -> &str {
&self.message
}
pub fn line(&self) -> Option<u32> {
self.line
}
pub fn column(&self) -> Option<u32> {
self.column
}
pub fn location(&self) -> Option<(u32, u32)> {
match (self.line, self.column) {
(Some(l), Some(c)) => Some((l, c)),
_ => None,
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match (self.line, self.column) {
(Some(line), Some(col)) => write!(f, "at {}:{}: {}", line, col, self.message),
(Some(line), None) => write!(f, "at line {}: {}", line, self.message),
_ => write!(f, "{}", self.message),
}
}
}
impl std::error::Error for ParseError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
Ffi(&'static str),
Parse(&'static str),
ParseError(ParseError),
Io(&'static str),
Alloc(&'static str),
Utf8(std::str::Utf8Error),
MutationWhileIterating,
TypeMismatch {
expected: &'static str,
got: &'static str,
},
DocumentMismatch,
ScalarTooLarge(usize),
}
impl Error {
pub fn as_parse_error(&self) -> Option<&ParseError> {
match self {
Error::ParseError(e) => Some(e),
_ => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Ffi(msg) => write!(f, "FFI error: {}", msg),
Error::Parse(msg) => write!(f, "Parse error: {}", msg),
Error::ParseError(e) => write!(f, "Parse error {}", e),
Error::Io(msg) => write!(f, "I/O error: {}", msg),
Error::Alloc(msg) => write!(f, "Allocation error: {}", msg),
Error::Utf8(e) => write!(f, "UTF-8 error: {}", e),
Error::MutationWhileIterating => {
write!(f, "Cannot mutate document while iterating")
}
Error::TypeMismatch { expected, got } => {
write!(f, "Type mismatch: expected {}, got {}", expected, got)
}
Error::DocumentMismatch => {
write!(f, "Nodes must belong to the same document")
}
Error::ScalarTooLarge(len) => {
write!(f, "Scalar length {} exceeds sanity limit", len)
}
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Utf8(e) => Some(e),
Error::ParseError(e) => Some(e),
_ => None,
}
}
}
impl From<std::str::Utf8Error> for Error {
fn from(e: std::str::Utf8Error) -> Self {
Error::Utf8(e)
}
}
impl From<ParseError> for Error {
fn from(e: ParseError) -> Self {
Error::ParseError(e)
}
}
pub type Result<T> = std::result::Result<T, Error>;