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 {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}