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