1 use serde::{de, ser};
2 use static_assertions::assert_impl_all;
3 use std::{convert::Infallible, error, fmt, result};
4 
5 /// Error type used by zvariant API.
6 #[derive(Debug)]
7 #[non_exhaustive]
8 pub enum Error {
9     /// Generic error. All serde errors gets transformed into this variant.
10     Message(String),
11 
12     /// Wrapper for [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)
13     Io(std::io::Error),
14     /// Type conversions errors.
15     IncorrectType,
16     /// Wrapper for [`std::str::Utf8Error`](https://doc.rust-lang.org/std/str/struct.Utf8Error.html)
17     Utf8(std::str::Utf8Error),
18     /// Non-0 padding byte(s) encountered.
19     PaddingNot0(u8),
20     /// The deserialized file descriptor is not in the given FD index.
21     UnknownFd,
22     /// Missing framing offset at the end of a GVariant-encoded container,
23     MissingFramingOffset,
24     /// The type (signature as first argument) being (de)serialized is not supported by the format.
25     IncompatibleFormat(crate::Signature<'static>, crate::EncodingFormat),
26     /// The provided signature (first argument) was not valid for reading as the requested type.
27     /// Details on the expected signatures are in the second argument.
28     SignatureMismatch(crate::Signature<'static>, String),
29 }
30 
31 assert_impl_all!(Error: Send, Sync, Unpin);
32 
33 impl PartialEq for Error {
eq(&self, other: &Self) -> bool34     fn eq(&self, other: &Self) -> bool {
35         match (self, other) {
36             (Error::Message(msg), Error::Message(other)) => msg == other,
37             // Io is false
38             (Error::IncorrectType, Error::IncorrectType) => true,
39             (Error::Utf8(msg), Error::Utf8(other)) => msg == other,
40             (Error::PaddingNot0(p), Error::PaddingNot0(other)) => p == other,
41             (Error::UnknownFd, Error::UnknownFd) => true,
42             (_, _) => false,
43         }
44     }
45 }
46 
47 impl error::Error for Error {
source(&self) -> Option<&(dyn error::Error + 'static)>48     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
49         match self {
50             Error::Io(e) => Some(e),
51             Error::Utf8(e) => Some(e),
52             _ => None,
53         }
54     }
55 }
56 
57 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result58     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59         match self {
60             Error::Message(s) => write!(f, "{}", s),
61             Error::Io(e) => e.fmt(f),
62             Error::IncorrectType => write!(f, "incorrect type"),
63             Error::Utf8(e) => write!(f, "{}", e),
64             Error::PaddingNot0(b) => write!(f, "Unexpected non-0 padding byte `{}`", b),
65             Error::UnknownFd => write!(f, "File descriptor not in the given FD index"),
66             Error::MissingFramingOffset => write!(
67                 f,
68                 "Missing framing offset at the end of GVariant-encoded container"
69             ),
70             Error::IncompatibleFormat(sig, format) => write!(
71                 f,
72                 "Type `{}` is not compatible with `{}` format",
73                 sig, format,
74             ),
75             Error::SignatureMismatch(provided, expected) => write!(
76                 f,
77                 "Signature mismatch: got `{}`, expected {}",
78                 provided, expected,
79             ),
80         }
81     }
82 }
83 
84 impl From<Infallible> for Error {
from(i: Infallible) -> Self85     fn from(i: Infallible) -> Self {
86         match i {}
87     }
88 }
89 
90 impl de::Error for Error {
91     // TODO: Add more specific error variants to Error enum above so we can implement other methods
92     // here too.
custom<T>(msg: T) -> Error where T: fmt::Display,93     fn custom<T>(msg: T) -> Error
94     where
95         T: fmt::Display,
96     {
97         Error::Message(msg.to_string())
98     }
99 }
100 
101 impl ser::Error for Error {
custom<T>(msg: T) -> Error where T: fmt::Display,102     fn custom<T>(msg: T) -> Error
103     where
104         T: fmt::Display,
105     {
106         Error::Message(msg.to_string())
107     }
108 }
109 
110 /// Alias for a `Result` with the error type `zvariant::Error`.
111 pub type Result<T> = result::Result<T, Error>;
112