1 | use serde::{de, ser}; |
2 | use static_assertions::assert_impl_all; |
3 | use std::{convert::Infallible, error, fmt, io, 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 | InputOutput(Arc<io::Error>), |
44 | /// Type conversions errors. |
45 | IncorrectType, |
46 | /// Wrapper for [`std::str::Utf8Error`](https://doc.rust-lang.org/std/str/struct.Utf8Error.html) |
47 | Utf8(std::str::Utf8Error), |
48 | /// Non-0 padding byte(s) encountered. |
49 | PaddingNot0(u8), |
50 | /// The deserialized file descriptor is not in the given FD index. |
51 | UnknownFd, |
52 | /// Missing framing offset at the end of a GVariant-encoded container, |
53 | MissingFramingOffset, |
54 | /// The type (signature as first argument) being (de)serialized is not supported by the format. |
55 | IncompatibleFormat(crate::Signature<'static>, crate::serialized::Format), |
56 | /// The provided signature (first argument) was not valid for reading as the requested type. |
57 | /// Details on the expected signatures are in the second argument. |
58 | SignatureMismatch(crate::Signature<'static>, String), |
59 | /// Out of bounds range specified. |
60 | OutOfBounds, |
61 | /// The maximum allowed depth for containers in encoding was exceeded. |
62 | MaxDepthExceeded(MaxDepthExceeded), |
63 | } |
64 | |
65 | assert_impl_all!(Error: Send, Sync, Unpin); |
66 | |
67 | impl PartialEq for Error { |
68 | fn eq(&self, other: &Self) -> bool { |
69 | match (self, other) { |
70 | (Error::Message(msg: &String), Error::Message(other: &String)) => msg == other, |
71 | // Io is false |
72 | (Error::IncorrectType, Error::IncorrectType) => true, |
73 | (Error::Utf8(msg: &Utf8Error), Error::Utf8(other: &Utf8Error)) => msg == other, |
74 | (Error::PaddingNot0(p: &u8), Error::PaddingNot0(other: &u8)) => p == other, |
75 | (Error::UnknownFd, Error::UnknownFd) => true, |
76 | (Error::MaxDepthExceeded(max1: &MaxDepthExceeded), Error::MaxDepthExceeded(max2: &MaxDepthExceeded)) => max1 == max2, |
77 | (_, _) => false, |
78 | } |
79 | } |
80 | } |
81 | |
82 | impl error::Error for Error { |
83 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
84 | match self { |
85 | Error::InputOutput(e: &Arc) => Some(e), |
86 | Error::Utf8(e: &Utf8Error) => Some(e), |
87 | _ => None, |
88 | } |
89 | } |
90 | } |
91 | |
92 | impl fmt::Display for Error { |
93 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
94 | match self { |
95 | Error::Message(s) => write!(f, " {s}" ), |
96 | Error::InputOutput(e) => e.fmt(f), |
97 | Error::IncorrectType => write!(f, "incorrect type" ), |
98 | Error::Utf8(e) => write!(f, " {e}" ), |
99 | Error::PaddingNot0(b) => write!(f, "Unexpected non-0 padding byte ` {b}`" ), |
100 | Error::UnknownFd => write!(f, "File descriptor not in the given FD index" ), |
101 | Error::MissingFramingOffset => write!( |
102 | f, |
103 | "Missing framing offset at the end of GVariant-encoded container" |
104 | ), |
105 | Error::IncompatibleFormat(sig, format) => { |
106 | write!(f, "Type ` {sig}` is not compatible with ` {format}` format" ,) |
107 | } |
108 | Error::SignatureMismatch(provided, expected) => write!( |
109 | f, |
110 | "Signature mismatch: got ` {provided}`, expected {expected}" , |
111 | ), |
112 | Error::OutOfBounds => write!( |
113 | f, |
114 | // FIXME: using the `Debug` impl of `Range` because it doesn't impl `Display`. |
115 | "Out of bounds range specified" , |
116 | ), |
117 | Error::MaxDepthExceeded(max) => write!(f, " {max}" ), |
118 | } |
119 | } |
120 | } |
121 | |
122 | impl Clone for Error { |
123 | fn clone(&self) -> Self { |
124 | match self { |
125 | Error::Message(s: &String) => Error::Message(s.clone()), |
126 | Error::InputOutput(e: &Arc) => Error::InputOutput(e.clone()), |
127 | Error::IncorrectType => Error::IncorrectType, |
128 | Error::Utf8(e: &Utf8Error) => Error::Utf8(*e), |
129 | Error::PaddingNot0(b: &u8) => Error::PaddingNot0(*b), |
130 | Error::UnknownFd => Error::UnknownFd, |
131 | Error::MissingFramingOffset => Error::MissingFramingOffset, |
132 | Error::IncompatibleFormat(sig: &Signature<'static>, format: &Format) => { |
133 | Error::IncompatibleFormat(sig.clone(), *format) |
134 | } |
135 | Error::SignatureMismatch(provided: &Signature<'static>, expected: &String) => { |
136 | Error::SignatureMismatch(provided.clone(), expected.clone()) |
137 | } |
138 | Error::OutOfBounds => Error::OutOfBounds, |
139 | Error::MaxDepthExceeded(max: &MaxDepthExceeded) => Error::MaxDepthExceeded(*max), |
140 | } |
141 | } |
142 | } |
143 | |
144 | impl From<Infallible> for Error { |
145 | fn from(i: Infallible) -> Self { |
146 | match i {} |
147 | } |
148 | } |
149 | |
150 | impl de::Error for Error { |
151 | // TODO: Add more specific error variants to Error enum above so we can implement other methods |
152 | // here too. |
153 | fn custom<T>(msg: T) -> Error |
154 | where |
155 | T: fmt::Display, |
156 | { |
157 | Error::Message(msg.to_string()) |
158 | } |
159 | } |
160 | |
161 | impl ser::Error for Error { |
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 From<io::Error> for Error { |
171 | fn from(val: io::Error) -> Self { |
172 | Error::InputOutput(Arc::new(data:val)) |
173 | } |
174 | } |
175 | |
176 | /// Alias for a `Result` with the error type `zvariant::Error`. |
177 | pub type Result<T> = result::Result<T, Error>; |
178 | |