use core::fmt;
use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Position {
pub byte_offset: usize,
pub column: Option<usize>,
pub line: Option<usize>,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
#[error("invalid event sequence: expected {expected}, found {found}: {message}")]
InvalidSequence {
expected: String,
found: String,
message: String,
},
#[error("I/O error: {source}")]
Io {
#[from]
source: std::io::Error,
},
#[error("{}", DisplayPos { label: "JSON error", message: message.as_str(), position: position.as_ref() })]
Json {
message: String,
position: Option<Position>,
},
#[error("{message}")]
Other {
message: String,
},
#[error("{}", DisplayPos { label: "parse error", message: message.as_str(), position: position.as_ref() })]
Parse {
message: String,
position: Option<Position>,
},
}
pub type Result<T> = core::result::Result<T, Error>;
struct DisplayPos<'a> {
label: &'a str,
message: &'a str,
position: Option<&'a Position>,
}
impl fmt::Display for DisplayPos<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.label)?;
if let Some(pos) = self.position {
let byte = pos.byte_offset;
match (pos.line, pos.column) {
(Some(line), Some(col)) => {
write!(f, " at line {line}, column {col} (byte {byte})")?;
}
(Some(line), _) => {
write!(f, " at line {line} (byte {byte})")?;
}
_ => {
write!(f, " at byte {byte}")?;
}
}
}
write!(f, ": {}", self.message)
}
}