1use std::fmt;
28
29#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct ParseError {
35 pub(crate) message: String,
37 pub(crate) line: Option<u32>,
39 pub(crate) column: Option<u32>,
41}
42
43impl ParseError {
44 pub fn new(message: impl Into<String>) -> Self {
46 Self {
47 message: message.into(),
48 line: None,
49 column: None,
50 }
51 }
52
53 pub fn with_location(message: impl Into<String>, line: u32, column: u32) -> Self {
55 Self {
56 message: message.into(),
57 line: Some(line),
58 column: Some(column),
59 }
60 }
61
62 pub fn message(&self) -> &str {
64 &self.message
65 }
66
67 pub fn line(&self) -> Option<u32> {
69 self.line
70 }
71
72 pub fn column(&self) -> Option<u32> {
74 self.column
75 }
76
77 pub fn location(&self) -> Option<(u32, u32)> {
79 match (self.line, self.column) {
80 (Some(l), Some(c)) => Some((l, c)),
81 _ => None,
82 }
83 }
84}
85
86impl fmt::Display for ParseError {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match (self.line, self.column) {
89 (Some(line), Some(col)) => write!(f, "at {}:{}: {}", line, col, self.message),
90 (Some(line), None) => write!(f, "at line {}: {}", line, self.message),
91 _ => write!(f, "{}", self.message),
92 }
93 }
94}
95
96impl std::error::Error for ParseError {}
97
98#[derive(Debug, Clone, PartialEq, Eq)]
100pub enum Error {
101 Ffi(&'static str),
103
104 Parse(&'static str),
106
107 ParseError(ParseError),
109
110 Io(&'static str),
112
113 Alloc(&'static str),
115
116 Utf8(std::str::Utf8Error),
118
119 MutationWhileIterating,
121
122 TypeMismatch {
124 expected: &'static str,
125 got: &'static str,
126 },
127
128 DocumentMismatch,
130
131 ScalarTooLarge(usize),
133}
134
135impl Error {
136 pub fn as_parse_error(&self) -> Option<&ParseError> {
138 match self {
139 Error::ParseError(e) => Some(e),
140 _ => None,
141 }
142 }
143}
144
145impl fmt::Display for Error {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 match self {
148 Error::Ffi(msg) => write!(f, "FFI error: {}", msg),
149 Error::Parse(msg) => write!(f, "Parse error: {}", msg),
150 Error::ParseError(e) => write!(f, "Parse error {}", e),
151 Error::Io(msg) => write!(f, "I/O error: {}", msg),
152 Error::Alloc(msg) => write!(f, "Allocation error: {}", msg),
153 Error::Utf8(e) => write!(f, "UTF-8 error: {}", e),
154 Error::MutationWhileIterating => {
155 write!(f, "Cannot mutate document while iterating")
156 }
157 Error::TypeMismatch { expected, got } => {
158 write!(f, "Type mismatch: expected {}, got {}", expected, got)
159 }
160 Error::DocumentMismatch => {
161 write!(f, "Nodes must belong to the same document")
162 }
163 Error::ScalarTooLarge(len) => {
164 write!(f, "Scalar length {} exceeds sanity limit", len)
165 }
166 }
167 }
168}
169
170impl std::error::Error for Error {
171 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
172 match self {
173 Error::Utf8(e) => Some(e),
174 Error::ParseError(e) => Some(e),
175 _ => None,
176 }
177 }
178}
179
180impl From<std::str::Utf8Error> for Error {
181 fn from(e: std::str::Utf8Error) -> Self {
182 Error::Utf8(e)
183 }
184}
185
186impl From<ParseError> for Error {
187 fn from(e: ParseError) -> Self {
188 Error::ParseError(e)
189 }
190}
191
192pub type Result<T> = std::result::Result<T, Error>;