summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_yaml/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/serde_yaml/src/error.rs')
-rw-r--r--third_party/rust/serde_yaml/src/error.rs244
1 files changed, 244 insertions, 0 deletions
diff --git a/third_party/rust/serde_yaml/src/error.rs b/third_party/rust/serde_yaml/src/error.rs
new file mode 100644
index 0000000000..dc8321435f
--- /dev/null
+++ b/third_party/rust/serde_yaml/src/error.rs
@@ -0,0 +1,244 @@
+use crate::path::Path;
+use serde::{de, ser};
+use std::error;
+use std::fmt::{self, Debug, Display};
+use std::io;
+use std::result;
+use std::str;
+use std::string;
+use std::sync::Arc;
+use yaml_rust::emitter;
+use yaml_rust::scanner::{self, Marker, ScanError};
+
+/// An error that happened serializing or deserializing YAML data.
+pub struct Error(Box<ErrorImpl>);
+
+/// Alias for a `Result` with the error type `serde_yaml::Error`.
+pub type Result<T> = result::Result<T, Error>;
+
+#[derive(Debug)]
+pub enum ErrorImpl {
+ Message(String, Option<Pos>),
+
+ Emit(emitter::EmitError),
+ Scan(scanner::ScanError),
+ Io(io::Error),
+ Utf8(str::Utf8Error),
+ FromUtf8(string::FromUtf8Error),
+
+ EndOfStream,
+ MoreThanOneDocument,
+ RecursionLimitExceeded,
+
+ Shared(Arc<ErrorImpl>),
+}
+
+#[derive(Debug)]
+pub struct Pos {
+ marker: Marker,
+ path: String,
+}
+
+/// The input location that an error occured.
+#[derive(Debug)]
+pub struct Location {
+ index: usize,
+ line: usize,
+ column: usize,
+}
+
+impl Location {
+ /// The byte index of the error
+ pub fn index(&self) -> usize {
+ self.index
+ }
+
+ /// The line of the error
+ pub fn line(&self) -> usize {
+ self.line
+ }
+
+ /// The column of the error
+ pub fn column(&self) -> usize {
+ self.column
+ }
+
+ // This is to keep decoupled with the yaml crate
+ #[doc(hidden)]
+ fn from_marker(marker: &Marker) -> Self {
+ Location {
+ // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value
+ column: marker.col() + 1,
+ index: marker.index(),
+ line: marker.line(),
+ }
+ }
+}
+
+impl Error {
+ /// Returns the Location from the error if one exists.
+ ///
+ /// Not all types of errors have a location so this can return `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use serde_yaml::{Value, Error};
+ /// #
+ /// // The `@` character as the first character makes this invalid yaml
+ /// let invalid_yaml: Result<Value, Error> = serde_yaml::from_str("@invalid_yaml");
+ ///
+ /// let location = invalid_yaml.unwrap_err().location().unwrap();
+ ///
+ /// assert_eq!(location.line(), 1);
+ /// assert_eq!(location.column(), 1);
+ /// ```
+ pub fn location(&self) -> Option<Location> {
+ match self.0.as_ref() {
+ ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)),
+ ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())),
+ _ => None,
+ }
+ }
+}
+
+pub(crate) fn end_of_stream() -> Error {
+ Error(Box::new(ErrorImpl::EndOfStream))
+}
+
+pub(crate) fn more_than_one_document() -> Error {
+ Error(Box::new(ErrorImpl::MoreThanOneDocument))
+}
+
+pub(crate) fn io(err: io::Error) -> Error {
+ Error(Box::new(ErrorImpl::Io(err)))
+}
+
+pub(crate) fn emitter(err: emitter::EmitError) -> Error {
+ Error(Box::new(ErrorImpl::Emit(err)))
+}
+
+pub(crate) fn scanner(err: scanner::ScanError) -> Error {
+ Error(Box::new(ErrorImpl::Scan(err)))
+}
+
+pub(crate) fn str_utf8(err: str::Utf8Error) -> Error {
+ Error(Box::new(ErrorImpl::Utf8(err)))
+}
+
+pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error {
+ Error(Box::new(ErrorImpl::FromUtf8(err)))
+}
+
+pub(crate) fn recursion_limit_exceeded() -> Error {
+ Error(Box::new(ErrorImpl::RecursionLimitExceeded))
+}
+
+pub(crate) fn shared(shared: Arc<ErrorImpl>) -> Error {
+ Error(Box::new(ErrorImpl::Shared(shared)))
+}
+
+pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error {
+ if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() {
+ *none = Some(Pos {
+ marker,
+ path: path.to_string(),
+ });
+ }
+ error
+}
+
+impl Error {
+ pub(crate) fn shared(self) -> Arc<ErrorImpl> {
+ if let ErrorImpl::Shared(err) = *self.0 {
+ err
+ } else {
+ Arc::from(self.0)
+ }
+ }
+}
+
+impl error::Error for Error {
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ self.0.source()
+ }
+}
+
+impl Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.0.display(f)
+ }
+}
+
+// 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 {
+ self.0.debug(f)
+ }
+}
+
+impl ser::Error for Error {
+ fn custom<T: Display>(msg: T) -> Self {
+ Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
+ }
+}
+
+impl de::Error for Error {
+ fn custom<T: Display>(msg: T) -> Self {
+ Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
+ }
+}
+
+impl ErrorImpl {
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ match self {
+ ErrorImpl::Scan(err) => Some(err),
+ ErrorImpl::Io(err) => Some(err),
+ ErrorImpl::Utf8(err) => Some(err),
+ ErrorImpl::FromUtf8(err) => Some(err),
+ ErrorImpl::Shared(err) => err.source(),
+ _ => None,
+ }
+ }
+
+ fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ ErrorImpl::Message(msg, None) => Display::fmt(msg, f),
+ ErrorImpl::Message(msg, Some(Pos { marker, path })) => {
+ if path == "." {
+ write!(f, "{}", ScanError::new(*marker, msg))
+ } else {
+ write!(f, "{}: {}", path, ScanError::new(*marker, msg))
+ }
+ }
+ ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"),
+ ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"),
+ ErrorImpl::Scan(err) => Display::fmt(err, f),
+ ErrorImpl::Io(err) => Display::fmt(err, f),
+ ErrorImpl::Utf8(err) => Display::fmt(err, f),
+ ErrorImpl::FromUtf8(err) => Display::fmt(err, f),
+ ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"),
+ ErrorImpl::MoreThanOneDocument => f.write_str(
+ "deserializing from YAML containing more than one document is not supported",
+ ),
+ ErrorImpl::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
+ ErrorImpl::Shared(err) => err.display(f),
+ }
+ }
+
+ fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(),
+ ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(),
+ ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(),
+ ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(),
+ ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(),
+ ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(),
+ ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(),
+ ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(),
+ ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(),
+ ErrorImpl::Shared(err) => err.debug(f),
+ }
+ }
+}