diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/ron/src/error.rs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/ron/src/error.rs')
-rw-r--r-- | third_party/rust/ron/src/error.rs | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/third_party/rust/ron/src/error.rs b/third_party/rust/ron/src/error.rs new file mode 100644 index 0000000000..406fb058c3 --- /dev/null +++ b/third_party/rust/ron/src/error.rs @@ -0,0 +1,445 @@ +use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; + +use serde::{de, ser}; + +use crate::parse::{is_ident_first_char, is_ident_other_char, is_ident_raw_char, BASE64_ENGINE}; + +/// This type represents all possible errors that can occur when +/// serializing or deserializing RON data. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SpannedError { + pub code: Error, + pub position: Position, +} + +pub type Result<T, E = Error> = std::result::Result<T, E>; +pub type SpannedResult<T> = std::result::Result<T, SpannedError>; + +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + Io(String), + Message(String), + Base64Error(base64::DecodeError), + Eof, + ExpectedArray, + ExpectedArrayEnd, + ExpectedAttribute, + ExpectedAttributeEnd, + ExpectedBoolean, + ExpectedComma, + ExpectedChar, + ExpectedFloat, + FloatUnderscore, + ExpectedInteger, + ExpectedOption, + ExpectedOptionEnd, + ExpectedMap, + ExpectedMapColon, + ExpectedMapEnd, + ExpectedDifferentStructName { + expected: &'static str, + found: String, + }, + ExpectedStructLike, + ExpectedNamedStructLike(&'static str), + ExpectedStructLikeEnd, + ExpectedUnit, + ExpectedString, + ExpectedStringEnd, + ExpectedIdentifier, + + InvalidEscape(&'static str), + + IntegerOutOfBounds, + + NoSuchExtension(String), + + UnclosedBlockComment, + UnderscoreAtBeginning, + UnexpectedByte(char), + + Utf8Error(Utf8Error), + TrailingCharacters, + + InvalidValueForType { + expected: String, + found: String, + }, + ExpectedDifferentLength { + expected: String, + found: usize, + }, + NoSuchEnumVariant { + expected: &'static [&'static str], + found: String, + outer: Option<String>, + }, + NoSuchStructField { + expected: &'static [&'static str], + found: String, + outer: Option<String>, + }, + MissingStructField { + field: &'static str, + outer: Option<String>, + }, + DuplicateStructField { + field: &'static str, + outer: Option<String>, + }, + InvalidIdentifier(String), + SuggestRawIdentifier(String), + ExceededRecursionLimit, +} + +impl fmt::Display for SpannedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if (self.position == Position { line: 0, col: 0 }) { + write!(f, "{}", self.code) + } else { + write!(f, "{}: {}", self.position, self.code) + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Error::Io(ref s) => f.write_str(s), + Error::Message(ref s) => f.write_str(s), + Error::Base64Error(ref e) => fmt::Display::fmt(e, f), + Error::Eof => f.write_str("Unexpected end of RON"), + Error::ExpectedArray => f.write_str("Expected opening `[`"), + Error::ExpectedArrayEnd => f.write_str("Expected closing `]`"), + Error::ExpectedAttribute => f.write_str("Expected an `#![enable(...)]` attribute"), + Error::ExpectedAttributeEnd => { + f.write_str("Expected closing `)]` after the enable attribute") + } + Error::ExpectedBoolean => f.write_str("Expected boolean"), + Error::ExpectedComma => f.write_str("Expected comma"), + Error::ExpectedChar => f.write_str("Expected char"), + Error::ExpectedFloat => f.write_str("Expected float"), + Error::FloatUnderscore => f.write_str("Unexpected underscore in float"), + Error::ExpectedInteger => f.write_str("Expected integer"), + Error::ExpectedOption => f.write_str("Expected option"), + Error::ExpectedOptionEnd => f.write_str("Expected closing `)`"), + Error::ExpectedMap => f.write_str("Expected opening `{`"), + Error::ExpectedMapColon => f.write_str("Expected colon"), + Error::ExpectedMapEnd => f.write_str("Expected closing `}`"), + Error::ExpectedDifferentStructName { + expected, + ref found, + } => write!( + f, + "Expected struct {} but found {}", + Identifier(expected), + Identifier(found) + ), + Error::ExpectedStructLike => f.write_str("Expected opening `(`"), + Error::ExpectedNamedStructLike(name) => { + if name.is_empty() { + f.write_str("Expected only opening `(`, no name, for un-nameable struct") + } else { + write!(f, "Expected opening `(` for struct {}", Identifier(name)) + } + } + Error::ExpectedStructLikeEnd => f.write_str("Expected closing `)`"), + Error::ExpectedUnit => f.write_str("Expected unit"), + Error::ExpectedString => f.write_str("Expected string"), + Error::ExpectedStringEnd => f.write_str("Expected end of string"), + Error::ExpectedIdentifier => f.write_str("Expected identifier"), + Error::InvalidEscape(s) => f.write_str(s), + Error::IntegerOutOfBounds => f.write_str("Integer is out of bounds"), + Error::NoSuchExtension(ref name) => { + write!(f, "No RON extension named {}", Identifier(name)) + } + Error::Utf8Error(ref e) => fmt::Display::fmt(e, f), + Error::UnclosedBlockComment => f.write_str("Unclosed block comment"), + Error::UnderscoreAtBeginning => { + f.write_str("Unexpected leading underscore in an integer") + } + Error::UnexpectedByte(ref byte) => write!(f, "Unexpected byte {:?}", byte), + Error::TrailingCharacters => f.write_str("Non-whitespace trailing characters"), + Error::InvalidValueForType { + ref expected, + ref found, + } => { + write!(f, "Expected {} but found {} instead", expected, found) + } + Error::ExpectedDifferentLength { + ref expected, + found, + } => { + write!(f, "Expected {} but found ", expected)?; + + match found { + 0 => f.write_str("zero elements")?, + 1 => f.write_str("one element")?, + n => write!(f, "{} elements", n)?, + } + + f.write_str(" instead") + } + Error::NoSuchEnumVariant { + expected, + ref found, + ref outer, + } => { + f.write_str("Unexpected ")?; + + if outer.is_none() { + f.write_str("enum ")?; + } + + write!(f, "variant named {}", Identifier(found))?; + + if let Some(outer) = outer { + write!(f, "in enum {}", Identifier(outer))?; + } + + write!( + f, + ", {}", + OneOf { + alts: expected, + none: "variants" + } + ) + } + Error::NoSuchStructField { + expected, + ref found, + ref outer, + } => { + write!(f, "Unexpected field named {}", Identifier(found))?; + + if let Some(outer) = outer { + write!(f, "in {}", Identifier(outer))?; + } + + write!( + f, + ", {}", + OneOf { + alts: expected, + none: "fields" + } + ) + } + Error::MissingStructField { field, ref outer } => { + write!(f, "Unexpected missing field {}", Identifier(field))?; + + match outer { + Some(outer) => write!(f, " in {}", Identifier(outer)), + None => Ok(()), + } + } + Error::DuplicateStructField { field, ref outer } => { + write!(f, "Unexpected duplicate field {}", Identifier(field))?; + + match outer { + Some(outer) => write!(f, " in {}", Identifier(outer)), + None => Ok(()), + } + } + Error::InvalidIdentifier(ref invalid) => write!(f, "Invalid identifier {:?}", invalid), + Error::SuggestRawIdentifier(ref identifier) => write!( + f, + "Found invalid std identifier `{}`, try the raw identifier `r#{}` instead", + identifier, identifier + ), + Error::ExceededRecursionLimit => f.write_str("Exceeded recursion limit, try increasing the limit and using `serde_stacker` to protect against a stack overflow"), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Position { + pub line: usize, + pub col: usize, +} + +impl fmt::Display for Position { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.line, self.col) + } +} + +impl ser::Error for Error { + #[cold] + fn custom<T: fmt::Display>(msg: T) -> Self { + Error::Message(msg.to_string()) + } +} + +impl de::Error for Error { + #[cold] + fn custom<T: fmt::Display>(msg: T) -> Self { + Error::Message(msg.to_string()) + } + + #[cold] + fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self { + // Invalid type and invalid value are merged given their similarity in ron + Self::invalid_value(unexp, exp) + } + + #[cold] + fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self { + struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>); + + impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use de::Unexpected::*; + + match self.0 { + Bool(b) => write!(f, "the boolean `{}`", b), + Unsigned(i) => write!(f, "the unsigned integer `{}`", i), + Signed(i) => write!(f, "the signed integer `{}`", i), + Float(n) => write!(f, "the floating point number `{}`", n), + Char(c) => write!(f, "the UTF-8 character `{}`", c), + Str(s) => write!(f, "the string {:?}", s), + Bytes(b) => write!(f, "the bytes \"{}\"", { + base64::display::Base64Display::new(b, &BASE64_ENGINE) + }), + Unit => write!(f, "a unit value"), + Option => write!(f, "an optional value"), + NewtypeStruct => write!(f, "a newtype struct"), + Seq => write!(f, "a sequence"), + Map => write!(f, "a map"), + Enum => write!(f, "an enum"), + UnitVariant => write!(f, "a unit variant"), + NewtypeVariant => write!(f, "a newtype variant"), + TupleVariant => write!(f, "a tuple variant"), + StructVariant => write!(f, "a struct variant"), + Other(other) => f.write_str(other), + } + } + } + + Error::InvalidValueForType { + expected: exp.to_string(), + found: UnexpectedSerdeTypeValue(unexp).to_string(), + } + } + + #[cold] + fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self { + Error::ExpectedDifferentLength { + expected: exp.to_string(), + found: len, + } + } + + #[cold] + fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { + Error::NoSuchEnumVariant { + expected, + found: variant.to_string(), + outer: None, + } + } + + #[cold] + fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { + Error::NoSuchStructField { + expected, + found: field.to_string(), + outer: None, + } + } + + #[cold] + fn missing_field(field: &'static str) -> Self { + Error::MissingStructField { field, outer: None } + } + + #[cold] + fn duplicate_field(field: &'static str) -> Self { + Error::DuplicateStructField { field, outer: None } + } +} + +impl StdError for SpannedError {} +impl StdError for Error {} + +impl From<Utf8Error> for Error { + fn from(e: Utf8Error) -> Self { + Error::Utf8Error(e) + } +} + +impl From<FromUtf8Error> for Error { + fn from(e: FromUtf8Error) -> Self { + Error::Utf8Error(e.utf8_error()) + } +} + +impl From<io::Error> for Error { + fn from(e: io::Error) -> Self { + Error::Io(e.to_string()) + } +} + +impl From<io::Error> for SpannedError { + fn from(e: io::Error) -> Self { + SpannedError { + code: e.into(), + position: Position { line: 0, col: 0 }, + } + } +} + +impl From<SpannedError> for Error { + fn from(e: SpannedError) -> Self { + e.code + } +} + +struct OneOf { + alts: &'static [&'static str], + none: &'static str, +} + +impl fmt::Display for OneOf { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.alts { + [] => write!(f, "there are no {}", self.none), + [a1] => write!(f, "expected {} instead", Identifier(a1)), + [a1, a2] => write!( + f, + "expected either {} or {} instead", + Identifier(a1), + Identifier(a2) + ), + [a1, ref alts @ ..] => { + write!(f, "expected one of {}", Identifier(a1))?; + + for alt in alts { + write!(f, ", {}", Identifier(alt))?; + } + + f.write_str(" instead") + } + } + } +} + +struct Identifier<'a>(&'a str); + +impl<'a> fmt::Display for Identifier<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0.is_empty() || !self.0.as_bytes().iter().copied().all(is_ident_raw_char) { + return write!(f, "{:?}_[invalid identifier]", self.0); + } + + let mut bytes = self.0.as_bytes().iter().copied(); + + if !bytes.next().map_or(false, is_ident_first_char) || !bytes.all(is_ident_other_char) { + write!(f, "`r#{}`", self.0) + } else { + write!(f, "`{}`", self.0) + } + } +} |