1use core::fmt;
4
5use thiserror::Error;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Position {
10 pub byte_offset: usize,
12 pub column: Option<usize>,
14 pub line: Option<usize>,
16}
17
18#[derive(Debug, Error)]
20#[non_exhaustive]
21pub enum Error {
22 #[error("invalid event sequence: expected {expected}, found {found}: {message}")]
24 InvalidSequence {
25 expected: String,
27 found: String,
29 message: String,
31 },
32 #[error("I/O error: {source}")]
34 Io {
35 #[from]
37 source: std::io::Error,
38 },
39 #[error("{}", DisplayPos { label: "JSON error", message: message.as_str(), position: position.as_ref() })]
41 Json {
42 message: String,
44 position: Option<Position>,
46 },
47 #[error("{message}")]
49 Other {
50 message: String,
52 },
53 #[error("{}", DisplayPos { label: "parse error", message: message.as_str(), position: position.as_ref() })]
55 Parse {
56 message: String,
58 position: Option<Position>,
60 },
61}
62
63pub type Result<T> = core::result::Result<T, Error>;
65
66struct DisplayPos<'a> {
67 label: &'a str,
68 message: &'a str,
69 position: Option<&'a Position>,
70}
71
72impl fmt::Display for DisplayPos<'_> {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "{}", self.label)?;
75 if let Some(pos) = self.position {
76 let byte = pos.byte_offset;
77 match (pos.line, pos.column) {
78 (Some(line), Some(col)) => {
79 write!(f, " at line {line}, column {col} (byte {byte})")?;
80 }
81 (Some(line), _) => {
82 write!(f, " at line {line} (byte {byte})")?;
83 }
84 _ => {
85 write!(f, " at byte {byte}")?;
86 }
87 }
88 }
89 write!(f, ": {}", self.message)
90 }
91}