Skip to main content

snix_serde/
error.rs

1//! When (de-)serialising Nix goes wrong ...
2
3use std::error;
4use std::fmt::Display;
5
6#[derive(Clone, Debug)]
7pub enum Error {
8    /// Attempted to deserialise an unsupported Nix value (such as a
9    /// function) that can not be represented by the
10    /// [`serde::Deserialize`] trait.
11    Unserializable { value_type: &'static str },
12
13    /// Expected to deserialize a value that is unsupported by Nix.
14    Unsupported { wanted: &'static str },
15
16    /// Expected a specific type, but got something else on the Nix side.
17    UnexpectedType {
18        expected: &'static str,
19        got: &'static str,
20    },
21
22    /// Deserialisation error returned from `serde::de`.
23    Deserialization(String),
24
25    /// Deserialized integer did not fit.
26    IntegerConversion { got: i64, need: &'static str },
27
28    /// Evaluation of the supplied Nix code failed while computing the
29    /// value for deserialisation.
30    NixErrors { errors: Vec<snix_eval::Error> },
31
32    /// Could not determine an externally tagged enum representation.
33    AmbiguousEnum,
34
35    /// Attempted to provide content to a unit enum.
36    UnitEnumContent,
37
38    /// Serialisation error returned from `serde::ser`.
39    Serialization(String),
40
41    /// Attempted to serialise a value with a non-string map key.
42    NonStringKey,
43
44    /// Attempted to serialise an integer that does not fit into i64.
45    IntegerOverflow { got: u64 },
46}
47
48impl Display for Error {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Error::Unserializable { value_type } => write!(
52                f,
53                "can not deserialise a Nix '{value_type}' into a Rust type"
54            ),
55
56            Error::Unsupported { wanted } => {
57                write!(f, "'{wanted}' is not supported by the Nix value model")
58            }
59
60            Error::UnexpectedType { expected, got } => {
61                write!(f, "expected type {expected}, but got Nix type {got}")
62            }
63
64            Error::NixErrors { errors } => {
65                writeln!(
66                    f,
67                    "{} occurred during Nix evaluation: ",
68                    if errors.len() == 1 { "error" } else { "errors" }
69                )?;
70
71                for err in errors {
72                    writeln!(f, "{}", err.fancy_format_str())?;
73                }
74
75                Ok(())
76            }
77
78            Error::Deserialization(err) => write!(f, "deserialisation error occurred: {err}"),
79
80            Error::IntegerConversion { got, need } => {
81                write!(f, "i64({got}) does not fit in a {need}")
82            }
83
84            Error::AmbiguousEnum => write!(f, "could not determine enum variant: ambiguous keys"),
85
86            Error::UnitEnumContent => write!(f, "provided content for unit enum variant"),
87
88            Error::Serialization(err) => write!(f, "serialisation error occurred: {err}"),
89
90            Error::NonStringKey => write!(f, "Nix attribute sets only support string keys"),
91
92            Error::IntegerOverflow { got } => {
93                write!(f, "u64({got}) does not fit in a Nix integer (i64)")
94            }
95        }
96    }
97}
98
99impl error::Error for Error {
100    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
101        match self {
102            Self::NixErrors { errors, .. } => errors.first().map(|e| e as &dyn error::Error),
103            _ => None,
104        }
105    }
106}
107
108impl serde::de::Error for Error {
109    fn custom<T>(err: T) -> Self
110    where
111        T: Display,
112    {
113        Self::Deserialization(err.to_string())
114    }
115}
116
117impl serde::ser::Error for Error {
118    fn custom<T>(err: T) -> Self
119    where
120        T: Display,
121    {
122        Self::Serialization(err.to_string())
123    }
124}