diff options
Diffstat (limited to 'vendor/serde_json/src/error.rs')
-rw-r--r-- | vendor/serde_json/src/error.rs | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/vendor/serde_json/src/error.rs b/vendor/serde_json/src/error.rs deleted file mode 100644 index 03555eb..0000000 --- a/vendor/serde_json/src/error.rs +++ /dev/null @@ -1,516 +0,0 @@ -//! When serializing or deserializing JSON goes wrong. - -use crate::io; -use alloc::boxed::Box; -use alloc::string::{String, ToString}; -use core::fmt::{self, Debug, Display}; -use core::result; -use core::str::FromStr; -use serde::{de, ser}; -#[cfg(feature = "std")] -use std::error; -#[cfg(feature = "std")] -use std::io::ErrorKind; - -/// This type represents all possible errors that can occur when serializing or -/// deserializing JSON data. -pub struct Error { - /// This `Box` allows us to keep the size of `Error` as small as possible. A - /// larger `Error` type was substantially slower due to all the functions - /// that pass around `Result<T, Error>`. - err: Box<ErrorImpl>, -} - -/// Alias for a `Result` with the error type `serde_json::Error`. -pub type Result<T> = result::Result<T, Error>; - -impl Error { - /// One-based line number at which the error was detected. - /// - /// Characters in the first line of the input (before the first newline - /// character) are in line 1. - pub fn line(&self) -> usize { - self.err.line - } - - /// One-based column number at which the error was detected. - /// - /// The first character in the input and any characters immediately - /// following a newline character are in column 1. - /// - /// Note that errors may occur in column 0, for example if a read from an - /// I/O stream fails immediately following a previously read newline - /// character. - pub fn column(&self) -> usize { - self.err.column - } - - /// Categorizes the cause of this error. - /// - /// - `Category::Io` - failure to read or write bytes on an I/O stream - /// - `Category::Syntax` - input that is not syntactically valid JSON - /// - `Category::Data` - input data that is semantically incorrect - /// - `Category::Eof` - unexpected end of the input data - pub fn classify(&self) -> Category { - match self.err.code { - ErrorCode::Message(_) => Category::Data, - ErrorCode::Io(_) => Category::Io, - ErrorCode::EofWhileParsingList - | ErrorCode::EofWhileParsingObject - | ErrorCode::EofWhileParsingString - | ErrorCode::EofWhileParsingValue => Category::Eof, - ErrorCode::ExpectedColon - | ErrorCode::ExpectedListCommaOrEnd - | ErrorCode::ExpectedObjectCommaOrEnd - | ErrorCode::ExpectedSomeIdent - | ErrorCode::ExpectedSomeValue - | ErrorCode::ExpectedDoubleQuote - | ErrorCode::InvalidEscape - | ErrorCode::InvalidNumber - | ErrorCode::NumberOutOfRange - | ErrorCode::InvalidUnicodeCodePoint - | ErrorCode::ControlCharacterWhileParsingString - | ErrorCode::KeyMustBeAString - | ErrorCode::ExpectedNumericKey - | ErrorCode::FloatKeyMustBeFinite - | ErrorCode::LoneLeadingSurrogateInHexEscape - | ErrorCode::TrailingComma - | ErrorCode::TrailingCharacters - | ErrorCode::UnexpectedEndOfHexEscape - | ErrorCode::RecursionLimitExceeded => Category::Syntax, - } - } - - /// Returns true if this error was caused by a failure to read or write - /// bytes on an I/O stream. - pub fn is_io(&self) -> bool { - self.classify() == Category::Io - } - - /// Returns true if this error was caused by input that was not - /// syntactically valid JSON. - pub fn is_syntax(&self) -> bool { - self.classify() == Category::Syntax - } - - /// Returns true if this error was caused by input data that was - /// semantically incorrect. - /// - /// For example, JSON containing a number is semantically incorrect when the - /// type being deserialized into holds a String. - pub fn is_data(&self) -> bool { - self.classify() == Category::Data - } - - /// Returns true if this error was caused by prematurely reaching the end of - /// the input data. - /// - /// Callers that process streaming input may be interested in retrying the - /// deserialization once more data is available. - pub fn is_eof(&self) -> bool { - self.classify() == Category::Eof - } - - /// The kind reported by the underlying standard library I/O error, if this - /// error was caused by a failure to read or write bytes on an I/O stream. - /// - /// # Example - /// - /// ``` - /// use serde_json::Value; - /// use std::io::{self, ErrorKind, Read}; - /// use std::process; - /// - /// struct ReaderThatWillTimeOut<'a>(&'a [u8]); - /// - /// impl<'a> Read for ReaderThatWillTimeOut<'a> { - /// fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - /// if self.0.is_empty() { - /// Err(io::Error::new(ErrorKind::TimedOut, "timed out")) - /// } else { - /// self.0.read(buf) - /// } - /// } - /// } - /// - /// fn main() { - /// let reader = ReaderThatWillTimeOut(br#" {"k": "#); - /// - /// let _: Value = match serde_json::from_reader(reader) { - /// Ok(value) => value, - /// Err(error) => { - /// if error.io_error_kind() == Some(ErrorKind::TimedOut) { - /// // Maybe this application needs to retry certain kinds of errors. - /// - /// # return; - /// } else { - /// eprintln!("error: {}", error); - /// process::exit(1); - /// } - /// } - /// }; - /// } - /// ``` - #[cfg(feature = "std")] - pub fn io_error_kind(&self) -> Option<ErrorKind> { - if let ErrorCode::Io(io_error) = &self.err.code { - Some(io_error.kind()) - } else { - None - } - } -} - -/// Categorizes the cause of a `serde_json::Error`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Category { - /// The error was caused by a failure to read or write bytes on an I/O - /// stream. - Io, - - /// The error was caused by input that was not syntactically valid JSON. - Syntax, - - /// The error was caused by input data that was semantically incorrect. - /// - /// For example, JSON containing a number is semantically incorrect when the - /// type being deserialized into holds a String. - Data, - - /// The error was caused by prematurely reaching the end of the input data. - /// - /// Callers that process streaming input may be interested in retrying the - /// deserialization once more data is available. - Eof, -} - -#[cfg(feature = "std")] -#[allow(clippy::fallible_impl_from)] -impl From<Error> for io::Error { - /// Convert a `serde_json::Error` into an `io::Error`. - /// - /// JSON syntax and data errors are turned into `InvalidData` I/O errors. - /// EOF errors are turned into `UnexpectedEof` I/O errors. - /// - /// ``` - /// use std::io; - /// - /// enum MyError { - /// Io(io::Error), - /// Json(serde_json::Error), - /// } - /// - /// impl From<serde_json::Error> for MyError { - /// fn from(err: serde_json::Error) -> MyError { - /// use serde_json::error::Category; - /// match err.classify() { - /// Category::Io => { - /// MyError::Io(err.into()) - /// } - /// Category::Syntax | Category::Data | Category::Eof => { - /// MyError::Json(err) - /// } - /// } - /// } - /// } - /// ``` - fn from(j: Error) -> Self { - if let ErrorCode::Io(err) = j.err.code { - err - } else { - match j.classify() { - Category::Io => unreachable!(), - Category::Syntax | Category::Data => io::Error::new(ErrorKind::InvalidData, j), - Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j), - } - } - } -} - -struct ErrorImpl { - code: ErrorCode, - line: usize, - column: usize, -} - -pub(crate) enum ErrorCode { - /// Catchall for syntax error messages - Message(Box<str>), - - /// Some I/O error occurred while serializing or deserializing. - Io(io::Error), - - /// EOF while parsing a list. - EofWhileParsingList, - - /// EOF while parsing an object. - EofWhileParsingObject, - - /// EOF while parsing a string. - EofWhileParsingString, - - /// EOF while parsing a JSON value. - EofWhileParsingValue, - - /// Expected this character to be a `':'`. - ExpectedColon, - - /// Expected this character to be either a `','` or a `']'`. - ExpectedListCommaOrEnd, - - /// Expected this character to be either a `','` or a `'}'`. - ExpectedObjectCommaOrEnd, - - /// Expected to parse either a `true`, `false`, or a `null`. - ExpectedSomeIdent, - - /// Expected this character to start a JSON value. - ExpectedSomeValue, - - /// Expected this character to be a `"`. - ExpectedDoubleQuote, - - /// Invalid hex escape code. - InvalidEscape, - - /// Invalid number. - InvalidNumber, - - /// Number is bigger than the maximum value of its type. - NumberOutOfRange, - - /// Invalid unicode code point. - InvalidUnicodeCodePoint, - - /// Control character found while parsing a string. - ControlCharacterWhileParsingString, - - /// Object key is not a string. - KeyMustBeAString, - - /// Contents of key were supposed to be a number. - ExpectedNumericKey, - - /// Object key is a non-finite float value. - FloatKeyMustBeFinite, - - /// Lone leading surrogate in hex escape. - LoneLeadingSurrogateInHexEscape, - - /// JSON has a comma after the last value in an array or map. - TrailingComma, - - /// JSON has non-whitespace trailing characters after the value. - TrailingCharacters, - - /// Unexpected end of hex escape. - UnexpectedEndOfHexEscape, - - /// Encountered nesting of JSON maps and arrays more than 128 layers deep. - RecursionLimitExceeded, -} - -impl Error { - #[cold] - pub(crate) fn syntax(code: ErrorCode, line: usize, column: usize) -> Self { - Error { - err: Box::new(ErrorImpl { code, line, column }), - } - } - - // Not public API. Should be pub(crate). - // - // Update `eager_json` crate when this function changes. - #[doc(hidden)] - #[cold] - pub fn io(error: io::Error) -> Self { - Error { - err: Box::new(ErrorImpl { - code: ErrorCode::Io(error), - line: 0, - column: 0, - }), - } - } - - #[cold] - pub(crate) fn fix_position<F>(self, f: F) -> Self - where - F: FnOnce(ErrorCode) -> Error, - { - if self.err.line == 0 { - f(self.err.code) - } else { - self - } - } -} - -impl Display for ErrorCode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - ErrorCode::Message(msg) => f.write_str(msg), - ErrorCode::Io(err) => Display::fmt(err, f), - ErrorCode::EofWhileParsingList => f.write_str("EOF while parsing a list"), - ErrorCode::EofWhileParsingObject => f.write_str("EOF while parsing an object"), - ErrorCode::EofWhileParsingString => f.write_str("EOF while parsing a string"), - ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"), - ErrorCode::ExpectedColon => f.write_str("expected `:`"), - ErrorCode::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"), - ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"), - ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"), - ErrorCode::ExpectedSomeValue => f.write_str("expected value"), - ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"), - ErrorCode::InvalidEscape => f.write_str("invalid escape"), - ErrorCode::InvalidNumber => f.write_str("invalid number"), - ErrorCode::NumberOutOfRange => f.write_str("number out of range"), - ErrorCode::InvalidUnicodeCodePoint => f.write_str("invalid unicode code point"), - ErrorCode::ControlCharacterWhileParsingString => { - f.write_str("control character (\\u0000-\\u001F) found while parsing a string") - } - ErrorCode::KeyMustBeAString => f.write_str("key must be a string"), - ErrorCode::ExpectedNumericKey => { - f.write_str("invalid value: expected key to be a number in quotes") - } - ErrorCode::FloatKeyMustBeFinite => { - f.write_str("float key must be finite (got NaN or +/-inf)") - } - ErrorCode::LoneLeadingSurrogateInHexEscape => { - f.write_str("lone leading surrogate in hex escape") - } - ErrorCode::TrailingComma => f.write_str("trailing comma"), - ErrorCode::TrailingCharacters => f.write_str("trailing characters"), - ErrorCode::UnexpectedEndOfHexEscape => f.write_str("unexpected end of hex escape"), - ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"), - } - } -} - -impl serde::de::StdError for Error { - #[cfg(feature = "std")] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match &self.err.code { - ErrorCode::Io(err) => err.source(), - _ => None, - } - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&*self.err, f) - } -} - -impl Display for ErrorImpl { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.line == 0 { - Display::fmt(&self.code, f) - } else { - write!( - f, - "{} at line {} column {}", - self.code, self.line, self.column - ) - } - } -} - -// Remove two layers of verbosity from the debug representation. Humans often -// end up seeing this representation because it is what unwrap() shows. -impl Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Error({:?}, line: {}, column: {})", - self.err.code.to_string(), - self.err.line, - self.err.column - ) - } -} - -impl de::Error for Error { - #[cold] - fn custom<T: Display>(msg: T) -> Error { - make_error(msg.to_string()) - } - - #[cold] - fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self { - if let de::Unexpected::Unit = unexp { - Error::custom(format_args!("invalid type: null, expected {}", exp)) - } else { - Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) - } - } -} - -impl ser::Error for Error { - #[cold] - fn custom<T: Display>(msg: T) -> Error { - make_error(msg.to_string()) - } -} - -// Parse our own error message that looks like "{} at line {} column {}" to work -// around erased-serde round-tripping the error through de::Error::custom. -fn make_error(mut msg: String) -> Error { - let (line, column) = parse_line_col(&mut msg).unwrap_or((0, 0)); - Error { - err: Box::new(ErrorImpl { - code: ErrorCode::Message(msg.into_boxed_str()), - line, - column, - }), - } -} - -fn parse_line_col(msg: &mut String) -> Option<(usize, usize)> { - let start_of_suffix = match msg.rfind(" at line ") { - Some(index) => index, - None => return None, - }; - - // Find start and end of line number. - let start_of_line = start_of_suffix + " at line ".len(); - let mut end_of_line = start_of_line; - while starts_with_digit(&msg[end_of_line..]) { - end_of_line += 1; - } - - if !msg[end_of_line..].starts_with(" column ") { - return None; - } - - // Find start and end of column number. - let start_of_column = end_of_line + " column ".len(); - let mut end_of_column = start_of_column; - while starts_with_digit(&msg[end_of_column..]) { - end_of_column += 1; - } - - if end_of_column < msg.len() { - return None; - } - - // Parse numbers. - let line = match usize::from_str(&msg[start_of_line..end_of_line]) { - Ok(line) => line, - Err(_) => return None, - }; - let column = match usize::from_str(&msg[start_of_column..end_of_column]) { - Ok(column) => column, - Err(_) => return None, - }; - - msg.truncate(start_of_suffix); - Some((line, column)) -} - -fn starts_with_digit(slice: &str) -> bool { - match slice.as_bytes().first() { - None => false, - Some(&byte) => byte >= b'0' && byte <= b'9', - } -} |