prost_reflect/dynamic/text_format/parse/
error.rs

1use logos::Span;
2use std::{
3    error::Error,
4    fmt::{self, Display},
5};
6
7/// An error that may occur while parsing the protobuf text format.
8#[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 {}, but found '{}'", expected, found),
131            ParseErrorKind::UnexpectedEof { expected, .. } => {
132                write!(f, "expected {}, but reached end of input", expected)
133            }
134            ParseErrorKind::IntegerValueOutOfRange {
135                expected, actual, ..
136            } => write!(
137                f,
138                "expected value to be {}, but the value {} is out of range",
139                expected, actual
140            ),
141            ParseErrorKind::FieldNotFound {
142                field_name,
143                message_name,
144                ..
145            } => write!(
146                f,
147                "field '{}' not found for message '{}'",
148                field_name, message_name
149            ),
150            ParseErrorKind::FieldAlreadySet { field_name, .. } => {
151                write!(f, "'{}' is already set", field_name,)
152            }
153            ParseErrorKind::OneofAlreadySet { oneof_name, .. } => {
154                write!(f, "a value is already set for oneof '{}'", oneof_name)
155            }
156            ParseErrorKind::ExtensionNotFound {
157                extension_name,
158                message_name,
159                ..
160            } => {
161                write!(
162                    f,
163                    "extension '{}' not found for message '{}'",
164                    extension_name, message_name
165                )
166            }
167            ParseErrorKind::MessageNotFound { message_name, .. } => {
168                write!(f, "message type '{}' not found", message_name)
169            }
170            ParseErrorKind::EnumValueNotFound {
171                value_name,
172                enum_name,
173                ..
174            } => {
175                write!(
176                    f,
177                    "value '{}' was not found for enum '{}'",
178                    value_name, enum_name
179                )
180            }
181            ParseErrorKind::InvalidTypeForAny { .. } => write!(
182                f,
183                "the field type must be 'google.protobuf.Any' to use Any expansion syntax"
184            ),
185            ParseErrorKind::InvalidMapKey { .. } => write!(f, "invalid value type for map key"),
186        }
187    }
188}
189
190impl Error for ParseErrorKind {}
191
192impl Display for ParseError {
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        self.kind.fmt(f)
195    }
196}
197
198impl Error for ParseError {}
199
200#[cfg(feature = "miette")]
201#[cfg_attr(docsrs, doc(cfg(feature = "miette")))]
202impl miette::Diagnostic for ParseError {
203    fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
204        self.kind.code()
205    }
206
207    fn severity(&self) -> Option<miette::Severity> {
208        self.kind.severity()
209    }
210
211    fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
212        self.kind.help()
213    }
214
215    fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
216        self.kind.url()
217    }
218
219    fn source_code(&self) -> Option<&dyn miette::SourceCode> {
220        Some(&self.source)
221    }
222
223    fn labels(&self) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
224        self.kind.labels()
225    }
226
227    fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
228        self.kind.related()
229    }
230
231    fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> {
232        self.kind.diagnostic_source()
233    }
234}