1use serde::{de, ser};
2use static_assertions::assert_impl_all;
3use std::{convert::Infallible, error, fmt, result, sync::Arc};
4
5/// Enum representing the max depth exceeded error.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum MaxDepthExceeded {
8 /// The maximum allowed depth for structures in encoding was exceeded.
9 Structure,
10 /// The maximum allowed depth for arrays in encoding was exceeded.
11 Array,
12 /// The maximum allowed depth for containers in encoding was exceeded.
13 Container,
14}
15
16impl fmt::Display for MaxDepthExceeded {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 match self {
19 Self::Structure => write!(
20 f,
21 "Maximum allowed depth for structures in encoding was exceeded"
22 ),
23 Self::Array => write!(
24 f,
25 "Maximum allowed depth for arrays in encoding was exceeded"
26 ),
27 Self::Container => write!(
28 f,
29 "Maximum allowed depth for containers in encoding was exceeded"
30 ),
31 }
32 }
33}
34
35/// Error type used by zvariant API.
36#[derive(Debug)]
37#[non_exhaustive]
38pub enum Error {
39 /// Generic error. All serde errors gets transformed into this variant.
40 Message(String),
41
42 /// Wrapper for [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)
43 #[deprecated(note = "Use `Error::InputOutput` instead")]
44 Io(std::io::Error),
45 /// Wrapper for [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)
46 InputOutput(Arc<std::io::Error>),
47 /// Type conversions errors.
48 IncorrectType,
49 /// Wrapper for [`std::str::Utf8Error`](https://doc.rust-lang.org/std/str/struct.Utf8Error.html)
50 Utf8(std::str::Utf8Error),
51 /// Non-0 padding byte(s) encountered.
52 PaddingNot0(u8),
53 /// The deserialized file descriptor is not in the given FD index.
54 UnknownFd,
55 /// Missing framing offset at the end of a GVariant-encoded container,
56 MissingFramingOffset,
57 /// The type (signature as first argument) being (de)serialized is not supported by the format.
58 IncompatibleFormat(crate::Signature<'static>, crate::EncodingFormat),
59 /// The provided signature (first argument) was not valid for reading as the requested type.
60 /// Details on the expected signatures are in the second argument.
61 SignatureMismatch(crate::Signature<'static>, String),
62 /// Out of bounds range specified.
63 OutOfBounds,
64 /// The maximum allowed depth for containers in encoding was exceeded.
65 MaxDepthExceeded(MaxDepthExceeded),
66}
67
68assert_impl_all!(Error: Send, Sync, Unpin);
69
70impl PartialEq for Error {
71 fn eq(&self, other: &Self) -> bool {
72 match (self, other) {
73 (Error::Message(msg: &String), Error::Message(other: &String)) => msg == other,
74 // Io is false
75 (Error::IncorrectType, Error::IncorrectType) => true,
76 (Error::Utf8(msg: &Utf8Error), Error::Utf8(other: &Utf8Error)) => msg == other,
77 (Error::PaddingNot0(p: &u8), Error::PaddingNot0(other: &u8)) => p == other,
78 (Error::UnknownFd, Error::UnknownFd) => true,
79 (Error::MaxDepthExceeded(max1: &MaxDepthExceeded), Error::MaxDepthExceeded(max2: &MaxDepthExceeded)) => max1 == max2,
80 (_, _) => false,
81 }
82 }
83}
84
85impl error::Error for Error {
86 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
87 match self {
88 #[allow(deprecated)]
89 Error::Io(e: &Error) => Some(e),
90 Error::InputOutput(e: &Arc) => Some(e),
91 Error::Utf8(e: &Utf8Error) => Some(e),
92 _ => None,
93 }
94 }
95}
96
97impl fmt::Display for Error {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 match self {
100 Error::Message(s) => write!(f, "{s}"),
101 #[allow(deprecated)]
102 Error::Io(e) => e.fmt(f),
103 Error::InputOutput(e) => e.fmt(f),
104 Error::IncorrectType => write!(f, "incorrect type"),
105 Error::Utf8(e) => write!(f, "{e}"),
106 Error::PaddingNot0(b) => write!(f, "Unexpected non-0 padding byte `{b}`"),
107 Error::UnknownFd => write!(f, "File descriptor not in the given FD index"),
108 Error::MissingFramingOffset => write!(
109 f,
110 "Missing framing offset at the end of GVariant-encoded container"
111 ),
112 Error::IncompatibleFormat(sig, format) => {
113 write!(f, "Type `{sig}` is not compatible with `{format}` format",)
114 }
115 Error::SignatureMismatch(provided, expected) => write!(
116 f,
117 "Signature mismatch: got `{provided}`, expected {expected}",
118 ),
119 Error::OutOfBounds => write!(
120 f,
121 // FIXME: using the `Debug` impl of `Range` because it doesn't impl `Display`.
122 "Out of bounds range specified",
123 ),
124 Error::MaxDepthExceeded(max) => write!(f, "{max}"),
125 }
126 }
127}
128
129impl Clone for Error {
130 fn clone(&self) -> Self {
131 match self {
132 Error::Message(s: &String) => Error::Message(s.clone()),
133 #[allow(deprecated)]
134 Error::Io(e: &Error) => Error::Message(e.to_string()),
135 Error::InputOutput(e: &Arc) => Error::InputOutput(e.clone()),
136 Error::IncorrectType => Error::IncorrectType,
137 Error::Utf8(e: &Utf8Error) => Error::Utf8(*e),
138 Error::PaddingNot0(b: &u8) => Error::PaddingNot0(*b),
139 Error::UnknownFd => Error::UnknownFd,
140 Error::MissingFramingOffset => Error::MissingFramingOffset,
141 Error::IncompatibleFormat(sig: &Signature<'_>, format: &EncodingFormat) => {
142 Error::IncompatibleFormat(sig.clone(), *format)
143 }
144 Error::SignatureMismatch(provided: &Signature<'_>, expected: &String) => {
145 Error::SignatureMismatch(provided.clone(), expected.clone())
146 }
147 Error::OutOfBounds => Error::OutOfBounds,
148 Error::MaxDepthExceeded(max: &MaxDepthExceeded) => Error::MaxDepthExceeded(*max),
149 }
150 }
151}
152
153impl From<Infallible> for Error {
154 fn from(i: Infallible) -> Self {
155 match i {}
156 }
157}
158
159impl de::Error for Error {
160 // TODO: Add more specific error variants to Error enum above so we can implement other methods
161 // here too.
162 fn custom<T>(msg: T) -> Error
163 where
164 T: fmt::Display,
165 {
166 Error::Message(msg.to_string())
167 }
168}
169
170impl ser::Error for Error {
171 fn custom<T>(msg: T) -> Error
172 where
173 T: fmt::Display,
174 {
175 Error::Message(msg.to_string())
176 }
177}
178
179/// Alias for a `Result` with the error type `zvariant::Error`.
180pub type Result<T> = result::Result<T, Error>;
181