1 | use serde::{de, ser}; |
2 | use static_assertions::assert_impl_all; |
3 | use std::{convert::Infallible, error, fmt, result, sync::Arc}; |
4 | |
5 | /// Enum representing the max depth exceeded error. |
6 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
7 | pub 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 | |
16 | impl 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 ] |
38 | pub 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 | |
68 | assert_impl_all!(Error: Send, Sync, Unpin); |
69 | |
70 | impl 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 | |
85 | impl 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 | |
97 | impl 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 | |
129 | impl 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 | |
153 | impl From<Infallible> for Error { |
154 | fn from(i: Infallible) -> Self { |
155 | match i {} |
156 | } |
157 | } |
158 | |
159 | impl 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 | |
170 | impl 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`. |
180 | pub type Result<T> = result::Result<T, Error>; |
181 | |