1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//! Errors associated with processing YAML.
use core::fmt;
use core::ops::Range;
/// An error raised by the YAML module.
#[derive(Debug)]
pub struct Error {
span: Range<usize>,
kind: ErrorKind,
}
impl Error {
/// Construct a new error.
#[inline]
pub(crate) const fn new(span: Range<usize>, kind: ErrorKind) -> Self {
Self { span, kind }
}
/// Get the range of the input span.
#[must_use]
#[inline]
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
/// Get the kind of an error.
#[must_use]
#[inline]
pub fn kind(&self) -> &ErrorKind {
&self.kind
}
}
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} (at {}-{})",
self.kind, self.span.start, self.span.end
)
}
}
impl core::error::Error for Error {}
/// The kind of an [`Error`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorKind {
/// Expect end of file.
///
/// # Examples
///
/// ```
/// use anyhow::Context;
/// use nondestructive::yaml;
///
/// const INPUT: &str = r"
/// {hello: world}
/// 42
/// ";
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::ExpectedEof);
/// assert_eq!(&INPUT[error.span()], "42\n");
/// ```
ExpectedEof,
/// Bad a sequence terminator.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r"[Aristotle, # this is a comment";
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadSequenceTerminator);
/// assert_eq!(&INPUT[error.span()], " # this is a comment");
/// ```
BadSequenceTerminator,
/// Bad mapping separator.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r"{name: Aristotle, age # this is a comment";
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadMappingSeparator);
/// assert_eq!(&INPUT[error.span()], " age # this is a comment");
/// ```
///
/// Missing terminator in a non-inline mapping:
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r"
/// name: Aristotle
/// age # end";
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadMappingSeparator);
/// assert_eq!(&INPUT[error.span()], "age # end");
/// ```
BadMappingSeparator,
/// Bad a mapping terminator.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r"{name: Aristotle, # this is a comment";
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadMappingTerminator);
/// assert_eq!(&INPUT[error.span()], " # this is a comment");
/// ```
BadMappingTerminator,
/// Not a valid escape sequence.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r#""hello \o1u world""#;
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadEscape);
/// assert_eq!(&INPUT[error.span()], "\\o");
/// ```
BadEscape,
/// Bad hex escape.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r#""hello \x1u world""#;
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadHexEscape);
/// assert_eq!(&INPUT[error.span()], "\\x1u");
/// ```
BadHexEscape,
/// Bad unicode escape.
///
/// # Examples
///
/// ```
/// use nondestructive::yaml;
///
/// const INPUT: &str = r#""hello \ud800 world""#;
///
/// let error = yaml::from_slice(INPUT).unwrap_err();
/// assert_eq!(*error.kind(), yaml::ErrorKind::BadUnicodeEscape);
/// assert_eq!(&INPUT[error.span()], "\\ud800");
/// ```
BadUnicodeEscape,
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::ExpectedEof => write!(f, "expected end-of-file"),
ErrorKind::BadSequenceTerminator => write!(f, "bad sequence terminator"),
ErrorKind::BadMappingSeparator => write!(f, "bad mapping separator"),
ErrorKind::BadMappingTerminator => write!(f, "bad mapping terminator"),
ErrorKind::BadEscape => write!(f, "bad escape"),
ErrorKind::BadHexEscape => write!(f, "bad hex escape"),
ErrorKind::BadUnicodeEscape => write!(f, "bad unicode escape"),
}
}
}