prost_reflect/dynamic/text_format/parse/
error.rs1use logos::Span;
2use std::{
3 error::Error,
4 fmt::{self, Display},
5};
6
7#[derive(Debug)]
9#[cfg_attr(docsrs, doc(cfg(feature = "text-format")))]
10pub struct ParseError {
11 kind: Box<ParseErrorKind>,
12 #[cfg(feature = "miette")]
13 source: String,
14}
15
16impl ParseError {
17 #[cfg(feature = "miette")]
18 pub(crate) fn new(kind: ParseErrorKind, source: &str) -> Self {
19 ParseError {
20 kind: Box::new(kind),
21 source: source.to_owned(),
22 }
23 }
24
25 #[cfg(not(feature = "miette"))]
26 pub(crate) fn new(kind: ParseErrorKind, _: &str) -> Self {
27 ParseError {
28 kind: Box::new(kind),
29 }
30 }
31}
32
33#[derive(Debug, Clone, PartialEq)]
34#[cfg_attr(feature = "miette", derive(miette::Diagnostic))]
35pub(crate) enum ParseErrorKind {
36 InvalidToken {
37 #[cfg_attr(feature = "miette", label("found here"))]
38 span: Span,
39 },
40 InvalidStringCharacters {
41 #[cfg_attr(feature = "miette", label("invalid characters"))]
42 span: Span,
43 },
44 InvalidStringEscape {
45 #[cfg_attr(feature = "miette", label("defined here"))]
46 span: Span,
47 },
48 InvalidUtf8String {
49 #[cfg_attr(feature = "miette", label("defined here"))]
50 span: Span,
51 },
52 NoSpaceBetweenIntAndIdent {
53 #[cfg_attr(feature = "miette", label("found here"))]
54 span: Span,
55 },
56 UnexpectedToken {
57 expected: String,
58 found: String,
59 #[cfg_attr(feature = "miette", label("found here"))]
60 span: Span,
61 },
62 UnexpectedEof {
63 expected: String,
64 },
65 #[cfg_attr(
66 feature = "miette",
67 diagnostic(help("the value must be between {min} and {max} inclusive"))
68 )]
69 IntegerValueOutOfRange {
70 expected: String,
71 actual: String,
72 min: String,
73 max: String,
74 #[cfg_attr(feature = "miette", label("defined here"))]
75 span: Span,
76 },
77 FieldNotFound {
78 field_name: String,
79 message_name: String,
80 #[cfg_attr(feature = "miette", label("set here"))]
81 span: Span,
82 },
83 FieldAlreadySet {
84 field_name: String,
85 #[cfg_attr(feature = "miette", label("set here"))]
86 span: Span,
87 },
88 OneofAlreadySet {
89 oneof_name: String,
90 #[cfg_attr(feature = "miette", label("set here"))]
91 span: Span,
92 },
93 ExtensionNotFound {
94 extension_name: String,
95 message_name: String,
96 #[cfg_attr(feature = "miette", label("set here"))]
97 span: Span,
98 },
99 MessageNotFound {
100 message_name: String,
101 #[cfg_attr(feature = "miette", label("used here"))]
102 span: Span,
103 },
104 EnumValueNotFound {
105 value_name: String,
106 enum_name: String,
107 #[cfg_attr(feature = "miette", label("used here"))]
108 span: Span,
109 },
110 InvalidTypeForAny {
111 #[cfg_attr(feature = "miette", label("used here"))]
112 span: Span,
113 },
114 InvalidMapKey,
115}
116
117impl Display for ParseErrorKind {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 match self {
120 ParseErrorKind::InvalidToken { .. } => write!(f, "invalid token"),
121 ParseErrorKind::InvalidStringCharacters { .. } => write!(f, "invalid string character"),
122 ParseErrorKind::InvalidStringEscape { .. } => write!(f, "invalid string escape"),
123 ParseErrorKind::InvalidUtf8String { .. } => write!(f, "string is not valid utf-8"),
124 ParseErrorKind::NoSpaceBetweenIntAndIdent { .. } => write!(
125 f,
126 "whitespace is required between an integer literal and an identifier"
127 ),
128 ParseErrorKind::UnexpectedToken {
129 expected, found, ..
130 } => write!(f, "expected {expected}, but found '{found}'"),
131 ParseErrorKind::UnexpectedEof { expected, .. } => {
132 write!(f, "expected {expected}, but reached end of input")
133 }
134 ParseErrorKind::IntegerValueOutOfRange {
135 expected, actual, ..
136 } => write!(
137 f,
138 "expected value to be {expected}, but the value {actual} is out of range"
139 ),
140 ParseErrorKind::FieldNotFound {
141 field_name,
142 message_name,
143 ..
144 } => write!(
145 f,
146 "field '{field_name}' not found for message '{message_name}'"
147 ),
148 ParseErrorKind::FieldAlreadySet { field_name, .. } => {
149 write!(f, "'{field_name}' is already set")
150 }
151 ParseErrorKind::OneofAlreadySet { oneof_name, .. } => {
152 write!(f, "a value is already set for oneof '{oneof_name}'")
153 }
154 ParseErrorKind::ExtensionNotFound {
155 extension_name,
156 message_name,
157 ..
158 } => {
159 write!(
160 f,
161 "extension '{extension_name}' not found for message '{message_name}'"
162 )
163 }
164 ParseErrorKind::MessageNotFound { message_name, .. } => {
165 write!(f, "message type '{message_name}' not found")
166 }
167 ParseErrorKind::EnumValueNotFound {
168 value_name,
169 enum_name,
170 ..
171 } => {
172 write!(
173 f,
174 "value '{value_name}' was not found for enum '{enum_name}'"
175 )
176 }
177 ParseErrorKind::InvalidTypeForAny { .. } => write!(
178 f,
179 "the field type must be 'google.protobuf.Any' to use Any expansion syntax"
180 ),
181 ParseErrorKind::InvalidMapKey => write!(f, "invalid value type for map key"),
182 }
183 }
184}
185
186impl Error for ParseErrorKind {}
187
188impl Display for ParseError {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 self.kind.fmt(f)
191 }
192}
193
194impl Error for ParseError {}
195
196#[cfg(feature = "miette")]
197#[cfg_attr(docsrs, doc(cfg(feature = "miette")))]
198impl miette::Diagnostic for ParseError {
199 fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
200 self.kind.code()
201 }
202
203 fn severity(&self) -> Option<miette::Severity> {
204 self.kind.severity()
205 }
206
207 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
208 self.kind.help()
209 }
210
211 fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
212 self.kind.url()
213 }
214
215 fn source_code(&self) -> Option<&dyn miette::SourceCode> {
216 Some(&self.source)
217 }
218
219 fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
220 self.kind.labels()
221 }
222
223 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
224 self.kind.related()
225 }
226
227 fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> {
228 self.kind.diagnostic_source()
229 }
230}