Skip to main content

serde_saphyr/
ser_error.rs

1use std::{fmt, io};
2
3/// Error type used by the YAML serializer.
4///
5/// This type is re-exported as `serde_saphyr::ser::Error` and is returned by
6/// the public serialization APIs (for example `serde_saphyr::to_string`).
7///
8/// It implements `serde::ser::Error`, which allows user `Serialize` impls and
9/// Serde derives to report failures via `S::Error::custom(...)`. Such
10/// free‑form messages are stored in the `Message` variant.
11///
12/// Other variants wrap concrete underlying failures that can occur while
13/// serializing:
14/// - `Format` wraps a `std::fmt::Error` produced when writing to a
15///   `fmt::Write` target.
16/// - `IO` wraps a `std::io::Error` produced when writing to an `io::Write`
17///   target.
18/// - `Unexpected` is used internally for invariant violations (e.g., around
19///   anchors). It should not normally surface; if it does, please file a bug.
20#[non_exhaustive]
21#[derive(Debug)]
22pub enum Error {
23    /// Free-form error.
24    Message { msg: String },
25    /// Wrapper for formatting errors.
26    Format { error: fmt::Error },
27    /// Wrapper for I/O errors.
28    IO { error: io::Error },
29    /// This is used with anchors and should normally not surface, please report bug if it does.
30    Unexpected { msg: String },
31    /// Options used would produce invalid YAML (0 indentation, etc)
32    InvalidOptions(String),
33}
34
35impl serde::ser::Error for Error {
36    fn custom<T: fmt::Display>(msg: T) -> Self {
37        Error::Message {
38            msg: msg.to_string(),
39        }
40    }
41}
42
43impl From<fmt::Error> for Error {
44    fn from(error: fmt::Error) -> Self {
45        Error::Format { error }
46    }
47}
48
49impl From<io::Error> for Error {
50    fn from(error: io::Error) -> Self {
51        Error::IO { error }
52    }
53}
54
55impl From<String> for Error {
56    fn from(message: String) -> Self {
57        Error::Message { msg: message }
58    }
59}
60
61impl From<&String> for Error {
62    fn from(message: &String) -> Self {
63        Error::Message {
64            msg: message.clone(),
65        }
66    }
67}
68
69impl From<&str> for Error {
70    fn from(message: &str) -> Self {
71        Error::Message {
72            msg: message.to_string(),
73        }
74    }
75}
76
77impl Error {
78    #[cold]
79    #[inline(never)]
80    pub(crate) fn unexpected(message: &str) -> Self {
81        Error::Unexpected {
82            msg: message.to_string(),
83        }
84    }
85}
86
87impl fmt::Display for Error {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        match self {
90            Error::Message { msg } => f.write_str(msg),
91            Error::Format { error } => write!(f, "formatting error: {error}"),
92            Error::IO { error } => write!(f, "I/O error: {error}"),
93            Error::Unexpected { msg } => write!(f, "unexpected internal error: {msg}"),
94            Error::InvalidOptions(msg) => write!(f, "invalid serialization options: {msg}"),
95        }
96    }
97}
98
99impl std::error::Error for Error {
100    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
101        match self {
102            Error::Message { .. } => None,
103            Error::Unexpected { .. } => None,
104            Error::Format { error } => Some(error),
105            Error::IO { error } => Some(error),
106            Error::InvalidOptions(_) => None,
107        }
108    }
109}