1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::fmt::{Debug, Display, Formatter, Result};
15 use std::ffi::IntoStringError;
16 use std::string::FromUtf8Error;
17 
18 /// Errors during parsing.
19 pub enum Error {
20     /// Parsing error.
21     Parsing(ParseError),
22 
23     /// Io error.
24     Io(std::io::Error),
25 
26     /// Parse number error.
27     ParseNumber,
28 
29     /// Utf8 transform error.
30     Utf8Transform,
31 
32     /// Type transform error.
33     TypeTransform,
34 
35     /// Reader error.
36     Reader(Box<dyn std::error::Error>),
37 
38     /// Incorrect serde usage error.
39     IncorrectSerdeUsage,
40 
41     /// Used to convert serde-related errors.
42     Custom(String),
43 
44     /// Exceeds the recursion limit.
45     ExceedRecursionLimit,
46 }
47 
48 /// The specific location and character of the error during parsing.
49 pub enum ParseError {
50     /// Undesired character (line number, character number, current character)
51     UnexpectedCharacter(usize, usize, char),
52 
53     /// Illegal UTF-8 character (line number)
54     InvalidUtf8Bytes(usize),
55 
56     /// Undesired end-of-file character (line number)
57     UnexpectedEndOfJson(usize),
58 
59     /// Expected Eof but not received (line number)
60     TrailingBytes(usize),
61 
62     /// The input sequence has not yet been parsed.
63     ParsingUnfinished,
64 
65     /// There is an extra comma after the last value in an array or map (line number, character number)
66     TrailingComma(usize, usize),
67 
68     /// A colon is missing (line number, character number)
69     MissingColon(usize, usize),
70 
71     /// A comma is missing (line number, character number)
72     MissingComma(usize, usize),
73 }
74 
75 impl Error {
new_reader<E: Into<Box<dyn std::error::Error>>>(e: E) -> Self76     pub(crate) fn new_reader<E: Into<Box<dyn std::error::Error>>>(e: E) -> Self {
77         Error::Reader(e.into())
78     }
79 }
80 
81 impl Debug for ParseError {
fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result82     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
83         match self {
84             Self::UnexpectedCharacter(line, pos, unexpected) => {
85                 write!(
86                     f,
87                     "[Line]: {line}, [Pos]: {pos}, [Error]: Unexpected character: "
88                 )?;
89                 let mut str = match *unexpected {
90                     '\u{8}' => Some("\'\\b\'"),
91                     '\u{b}' => Some("\'\\v\'"),
92                     '\u{c}' => Some("\'\\f\'"),
93                     _ => None,
94                 };
95                 if let Some(s) = str.take() {
96                     write!(f, "{s}.")
97                 } else {
98                     write!(f, "{unexpected:?}.")
99                 }
100             }
101             Self::InvalidUtf8Bytes(line) => {
102                 write!(f, "[line]: {line}, [Error]: Invalid UTF-8 byte.")
103             }
104             Self::UnexpectedEndOfJson(line) => {
105                 write!(f, "[Line]: {line}, [Error]: Unexpected end of json.")
106             }
107             Self::TrailingBytes(line) => {
108                 write!(f, "[Line]: {line}, [Error]: Expected end of json but not.")
109             }
110             Self::ParsingUnfinished => {
111                 write!(f, "[Error]: Value has not been fully deserialized.")
112             }
113             Self::TrailingComma(line, pos) => {
114                 write!(
115                     f,
116                     "[Line]: {line}, [Pos]: {pos}, [Error]: Has a comma after the last value in an array or map."
117                 )
118             }
119             Self::MissingColon(line, pos) => {
120                 write!(f, "[Line]: {line}, [Pos]: {pos}, [Error]: A colon is missing between key and value.")
121             }
122             Self::MissingComma(line, pos) => {
123                 write!(
124                     f,
125                     "[Line]: {line}, [Pos]: {pos}, [Error]: A comma is missing before next value."
126                 )
127             }
128         }
129     }
130 }
131 
132 impl Debug for Error {
fmt(&self, f: &mut Formatter<'_>) -> Result133     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
134         match self {
135             Self::Parsing(e) => write!(f, "Parse Error: {e:?}"),
136             Self::Io(e) => write!(f, "Io Error: {e:?}"),
137             Self::ParseNumber => write!(f, "Parse Number Error"),
138             Self::TypeTransform => write!(f, "Type Transform Error"),
139             Self::Utf8Transform => write!(f, "Utf8 Transform Error"),
140             Self::IncorrectSerdeUsage => write!(f, "Incorrect Serde Usage Error"),
141             Self::Custom(s) => write!(f, "{s}"),
142             Self::Reader(e) => write!(f, "Reader Error:{e:?}"),
143             Self::ExceedRecursionLimit => write!(f, "Exceed the recursion limit"),
144         }
145     }
146 }
147 
148 impl Display for Error {
fmt(&self, f: &mut Formatter<'_>) -> Result149     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
150         Debug::fmt(self, f)
151     }
152 }
153 
154 impl From<ParseError> for Error {
from(e: ParseError) -> Self155     fn from(e: ParseError) -> Self {
156         Error::Parsing(e)
157     }
158 }
159 
160 impl From<core::str::Utf8Error> for Error {
from(_: core::str::Utf8Error) -> Self161     fn from(_: core::str::Utf8Error) -> Self {
162         Error::Utf8Transform
163     }
164 }
165 
166 impl From<std::io::Error> for Error {
from(e: std::io::Error) -> Self167     fn from(e: std::io::Error) -> Self {
168         Error::Io(e)
169     }
170 }
171 
172 impl std::error::Error for Error {}
173 
174 impl serde::ser::Error for Error {
custom<T>(msg: T) -> Self where T: Display,175     fn custom<T>(msg: T) -> Self
176     where
177         T: Display,
178     {
179         Error::Custom(msg.to_string())
180     }
181 }
182 
183 impl serde::de::Error for Error {
custom<T>(msg: T) -> Self where T: Display,184     fn custom<T>(msg: T) -> Self
185     where
186         T: Display,
187     {
188         Error::Custom(msg.to_string())
189     }
190 }
191 
192 impl From<FromUtf8Error> for Error {
from(_: FromUtf8Error) -> Self193     fn from(_: FromUtf8Error) -> Self {
194         Error::Utf8Transform
195     }
196 }
197 
198 impl From<IntoStringError> for Error {
from(_: IntoStringError) -> Self199     fn from(_: IntoStringError) -> Self {
200         Error::TypeTransform
201     }
202 }
203 
204 #[cfg(test)]
205 mod ut_error {
206     use crate::{Error, ParseError};
207     use std::ffi::CString;
208     use std::io::ErrorKind;
209 
210     /// UT test for `Error::fmt`.
211     ///
212     /// # Title
213     /// ut_error_fmt
214     ///
215     /// # Brief
216     /// 1. Creates a `Error`.
217     /// 2. Calls `Error::fmt` on this error.
218     /// 3. Checks if the results are correct.
219     #[test]
ut_error_fmt()220     fn ut_error_fmt() {
221         assert_eq!(
222             format!(
223                 "{:?}",
224                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, 'a'))
225             ),
226             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: 'a'.",
227         );
228 
229         assert_eq!(
230             format!(
231                 "{:?}",
232                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{8}'))
233             ),
234             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\b'.",
235         );
236 
237         assert_eq!(
238             format!(
239                 "{:?}",
240                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{b}'))
241             ),
242             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\v'.",
243         );
244 
245         assert_eq!(
246             format!(
247                 "{:?}",
248                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{c}'))
249             ),
250             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\f'.",
251         );
252 
253         assert_eq!(
254             format!("{:?}", Error::Parsing(ParseError::InvalidUtf8Bytes(1))),
255             "Parse Error: [line]: 1, [Error]: Invalid UTF-8 byte.",
256         );
257 
258         assert_eq!(
259             format!("{:?}", Error::Parsing(ParseError::UnexpectedEndOfJson(1))),
260             "Parse Error: [Line]: 1, [Error]: Unexpected end of json.",
261         );
262 
263         assert_eq!(
264             format!("{:?}", Error::Parsing(ParseError::TrailingBytes(1))),
265             "Parse Error: [Line]: 1, [Error]: Expected end of json but not.",
266         );
267 
268         assert_eq!(
269             format!("{:?}", Error::Parsing(ParseError::ParsingUnfinished)),
270             "Parse Error: [Error]: Value has not been fully deserialized.",
271         );
272 
273         assert_eq!(
274             format!(
275                 "{:?}",
276                 Error::Io(std::io::Error::from(ErrorKind::AddrInUse))
277             ),
278             "Io Error: Kind(AddrInUse)",
279         );
280 
281         assert_eq!(format!("{:?}", Error::ParseNumber), "Parse Number Error",);
282 
283         assert_eq!(
284             format!("{:?}", Error::Utf8Transform),
285             "Utf8 Transform Error",
286         );
287 
288         assert_eq!(
289             format!("{:?}", Error::TypeTransform),
290             "Type Transform Error",
291         );
292 
293         assert_eq!(
294             format!("{:?}", Error::IncorrectSerdeUsage),
295             "Incorrect Serde Usage Error",
296         );
297 
298         assert_eq!(
299             format!("{:?}", Error::Custom(String::from("Custom Error"))),
300             "Custom Error",
301         );
302 
303         assert_eq!(
304             format!("{:?}", Error::ExceedRecursionLimit),
305             "Exceed the recursion limit",
306         );
307 
308         assert_eq!(
309             format!(
310                 "{:?}",
311                 Error::Reader(std::io::Error::from(ErrorKind::AddrInUse).into())
312             ),
313             "Reader Error:Kind(AddrInUse)",
314         );
315 
316         assert_eq!(
317             format!(
318                 "{}",
319                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, 'a'))
320             ),
321             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: 'a'.",
322         );
323 
324         assert_eq!(
325             format!(
326                 "{}",
327                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{8}'))
328             ),
329             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\b'.",
330         );
331 
332         assert_eq!(
333             format!(
334                 "{}",
335                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{b}'))
336             ),
337             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\v'.",
338         );
339 
340         assert_eq!(
341             format!(
342                 "{}",
343                 Error::Parsing(ParseError::UnexpectedCharacter(1, 1, '\u{c}'))
344             ),
345             "Parse Error: [Line]: 1, [Pos]: 1, [Error]: Unexpected character: '\\f'.",
346         );
347 
348         assert_eq!(
349             format!("{}", Error::Parsing(ParseError::InvalidUtf8Bytes(1))),
350             "Parse Error: [line]: 1, [Error]: Invalid UTF-8 byte.",
351         );
352 
353         assert_eq!(
354             format!("{}", Error::Parsing(ParseError::UnexpectedEndOfJson(1))),
355             "Parse Error: [Line]: 1, [Error]: Unexpected end of json.",
356         );
357 
358         assert_eq!(
359             format!("{}", Error::Parsing(ParseError::TrailingBytes(1))),
360             "Parse Error: [Line]: 1, [Error]: Expected end of json but not.",
361         );
362 
363         assert_eq!(
364             format!("{}", Error::Io(std::io::Error::from(ErrorKind::AddrInUse))),
365             "Io Error: Kind(AddrInUse)",
366         );
367 
368         assert_eq!(format!("{}", Error::ParseNumber), "Parse Number Error",);
369 
370         assert_eq!(format!("{}", Error::Utf8Transform), "Utf8 Transform Error",);
371 
372         assert_eq!(format!("{}", Error::TypeTransform), "Type Transform Error",);
373 
374         assert_eq!(
375             format!(
376                 "{}",
377                 Error::Reader(std::io::Error::from(ErrorKind::AddrInUse).into())
378             ),
379             "Reader Error:Kind(AddrInUse)",
380         );
381     }
382 
383     /// UT test for `Error::from`.
384     ///
385     /// # Title
386     /// ut_error_from
387     ///
388     /// # Brief
389     /// 1. Creates some other errors.
390     /// 2. Calls `Error::from` on those error.
391     /// 3. Checks if the results are correct.
392     #[test]
ut_error_from()393     fn ut_error_from() {
394         assert_eq!(
395             format!("{}", Error::from(ParseError::TrailingBytes(1))),
396             "Parse Error: [Line]: 1, [Error]: Expected end of json but not.",
397         );
398 
399         assert_eq!(
400             format!(
401                 "{}",
402                 Error::from(std::io::Error::from(ErrorKind::AddrInUse))
403             ),
404             "Io Error: Kind(AddrInUse)",
405         );
406 
407         let str_vec = [0b10000000u8; 1];
408         assert_eq!(
409             format!(
410                 "{}",
411                 Error::from(std::str::from_utf8(&str_vec).err().unwrap())
412             ),
413             "Utf8 Transform Error",
414         );
415 
416         assert_eq!(
417             format!(
418                 "{}",
419                 Error::from(String::from_utf8(vec![129, 129, 129]).err().unwrap())
420             ),
421             "Utf8 Transform Error",
422         );
423 
424         assert_eq!(
425             format!(
426                 "{}",
427                 Error::from(
428                     CString::new(vec![129, 129, 129])
429                         .expect("CString::new failed")
430                         .into_string()
431                         .err()
432                         .unwrap()
433                 )
434             ),
435             "Type Transform Error",
436         );
437     }
438 }
439