1use crate::handle::{ObjectType, Rights};
8use std::sync::Arc;
9use zx_status::Status;
10
11pub type Result<T, E = Error> = std::result::Result<T, E>;
13
14#[derive(Debug, Clone, thiserror::Error)]
15#[allow(missing_docs)]
16pub enum TransportError {
17 #[error(transparent)]
18 Status(#[from] Status),
19 #[error(transparent)]
20 Other(Arc<dyn std::error::Error + Send + Sync>),
21}
22
23impl Drop for TransportError {
25 #[inline(never)]
26 fn drop(&mut self) {}
27}
28
29#[derive(Copy, Clone, Debug, Eq, PartialEq)]
32pub enum Epitaph {
33 Explicit(std::result::Result<(), zx_status::Status>),
36 PeerClosed,
38}
39
40impl std::fmt::Display for Epitaph {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match self {
43 Epitaph::Explicit(Ok(())) => write!(f, "ZX_OK (0)"),
44 Epitaph::Explicit(Err(s)) => write!(f, "{}", s),
45 Epitaph::PeerClosed => write!(f, "{}", zx_status::Status::PEER_CLOSED),
46 }
47 }
48}
49
50impl std::error::Error for Epitaph {
51 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
52 match self {
53 Epitaph::Explicit(Ok(())) | Epitaph::PeerClosed => None,
54 Epitaph::Explicit(Err(s)) => Some(s),
55 }
56 }
57}
58
59impl Epitaph {
60 pub fn is_explicit(&self) -> bool {
62 matches!(self, Epitaph::Explicit(_))
63 }
64
65 pub fn is_peer_closed(&self) -> bool {
68 matches!(self, Epitaph::PeerClosed | Epitaph::Explicit(Err(zx_status::Status::PEER_CLOSED)))
69 }
70
71 pub fn is_ok(&self) -> bool {
73 matches!(self, Epitaph::Explicit(Ok(())))
74 }
75}
76
77impl PartialEq<zx_status::Status> for Epitaph {
78 fn eq(&self, other: &zx_status::Status) -> bool {
79 match self {
80 Epitaph::Explicit(Ok(())) => *other == zx_status::Status::OK,
81 Epitaph::Explicit(Err(s)) => s == other,
82 Epitaph::PeerClosed => *other == zx_status::Status::PEER_CLOSED,
83 }
84 }
85}
86
87impl PartialEq<Epitaph> for zx_status::Status {
88 fn eq(&self, other: &Epitaph) -> bool {
89 other.eq(self)
90 }
91}
92
93impl PartialEq<std::result::Result<(), zx_status::Status>> for Epitaph {
94 fn eq(&self, other: &std::result::Result<(), zx_status::Status>) -> bool {
95 let res: std::result::Result<(), zx_status::Status> = (*self).into();
96 &res == other
97 }
98}
99
100impl PartialEq<Epitaph> for std::result::Result<(), zx_status::Status> {
101 fn eq(&self, other: &Epitaph) -> bool {
102 other.eq(self)
103 }
104}
105
106impl From<Epitaph> for std::result::Result<(), zx_status::Status> {
107 fn from(epitaph: Epitaph) -> Self {
108 match epitaph {
109 Epitaph::Explicit(res) => res,
110 Epitaph::PeerClosed => Err(zx_status::Status::PEER_CLOSED),
111 }
112 }
113}
114
115impl From<&Epitaph> for std::result::Result<(), zx_status::Status> {
116 fn from(epitaph: &Epitaph) -> Self {
117 (*epitaph).into()
118 }
119}
120
121impl From<zx_status::Status> for Epitaph {
122 fn from(status: zx_status::Status) -> Self {
123 if status == zx_status::Status::OK {
124 Epitaph::Explicit(Ok(()))
125 } else {
126 Epitaph::Explicit(Err(status))
127 }
128 }
129}
130
131impl From<std::result::Result<(), zx_status::Status>> for Epitaph {
132 fn from(res: std::result::Result<(), zx_status::Status>) -> Self {
133 Epitaph::Explicit(res)
134 }
135}
136
137#[derive(Debug, Clone, thiserror::Error)]
139#[non_exhaustive]
140#[allow(missing_docs)]
141pub enum Error {
142 #[error("Unexpected response to synchronous FIDL query.")]
143 UnexpectedSyncResponse,
144
145 #[error("Invalid FIDL boolean.")]
146 InvalidBoolean,
147
148 #[error("Invalid header for a FIDL buffer.")]
149 InvalidHeader,
150
151 #[error("Incompatible wire format magic number: {0}.")]
152 IncompatibleMagicNumber(u8),
153
154 #[error("Unsupported wire format version")]
155 UnsupportedWireFormatVersion,
156
157 #[error("Invalid FIDL buffer.")]
158 Invalid,
159
160 #[error(
161 "The FIDL object of size {expected} could not fit within the provided \
162 buffer range of size {actual}."
163 )]
164 OutOfRange { expected: usize, actual: usize },
165
166 #[error(
167 "The FIDL object requested more handles during decoding than were \
168 provided with the message."
169 )]
170 OutOfHandles,
171
172 #[error("Decoding the FIDL object did not use all of the bytes provided.")]
173 ExtraBytes,
174
175 #[error("Decoding the FIDL object did not use all of the handles provided.")]
176 ExtraHandles,
177
178 #[error(
179 "Decoding the FIDL object observed non-zero value in the padding region \
180 starting at byte {padding_start}."
181 )]
182 NonZeroPadding {
183 padding_start: usize,
185 },
186
187 #[error("The FIDL object had too many layers of out-of-line recursion.")]
188 MaxRecursionDepth,
189
190 #[error(
191 "There was an attempt to read or write a null-valued object as a non-nullable FIDL type."
192 )]
193 NotNullable,
194
195 #[error("A FIDL object reference with nonzero byte length had a null data pointer.")]
196 UnexpectedNullRef,
197
198 #[error("A FIDL message contained incorrectly encoded UTF8.")]
199 Utf8Error,
200
201 #[error("Vector was too long. Expected at most {max_length} elements, got {actual_length}.")]
202 VectorTooLong {
203 max_length: usize,
205 actual_length: usize,
207 },
208
209 #[error("String was too long. Expected at most {max_bytes} bytes, got {actual_bytes}.")]
210 StringTooLong {
211 max_bytes: usize,
213 actual_bytes: usize,
215 },
216
217 #[error(
218 "A message was received for ordinal value {ordinal} that the FIDL \
219 protocol {protocol_name} does not understand."
220 )]
221 UnknownOrdinal { ordinal: u64, protocol_name: &'static str },
222
223 #[error("Server for the FIDL protocol {protocol_name} did not recognize method {method_name}.")]
224 UnsupportedMethod { method_name: &'static str, protocol_name: &'static str },
225
226 #[error("Invalid bits value for a strict bits type.")]
227 InvalidBitsValue,
228
229 #[error("Invalid enum value for a strict enum type.")]
230 InvalidEnumValue,
231
232 #[error("Unrecognized descriminant for a FIDL union type.")]
233 UnknownUnionTag,
234
235 #[error("A FIDL future was polled after it had already completed.")]
236 PollAfterCompletion,
237
238 #[error(
239 "Received request with zero txid for two-way method ordinal, \
240 or nonzero txid for one-way method ordinal."
241 )]
242 InvalidRequestTxid,
243
244 #[error("Received response with unknown txid.")]
245 InvalidResponseTxid,
246
247 #[error("Received response with unexpected ordinal.")]
248 InvalidResponseOrdinal,
249
250 #[error("Invalid presence indicator.")]
251 InvalidPresenceIndicator,
252
253 #[error("Invalid inline bit in envelope.")]
254 InvalidInlineBitInEnvelope,
255
256 #[error("Invalid inline marker in envelope.")]
257 InvalidInlineMarkerInEnvelope,
258
259 #[error("Invalid number of bytes in FIDL envelope.")]
260 InvalidNumBytesInEnvelope,
261
262 #[error("Invalid number of handles in FIDL envelope.")]
263 InvalidNumHandlesInEnvelope,
264
265 #[error("Invalid FIDL handle used on the host.")]
266 InvalidHostHandle,
267
268 #[error("Incorrect handle subtype. Expected {}, but received {}", .expected.into_raw(), .received.into_raw())]
269 IncorrectHandleSubtype { expected: ObjectType, received: ObjectType },
270
271 #[error("Some expected handle rights are missing: {}", .missing_rights.bits())]
272 MissingExpectedHandleRights { missing_rights: Rights },
273
274 #[error("An error was encountered during handle replace()")]
275 HandleReplace(#[source] Status),
276
277 #[error("A server encountered an IO error writing a FIDL response to a channel: {0}")]
278 ServerResponseWrite(#[source] TransportError),
279
280 #[error(
281 "A FIDL server encountered an IO error reading incoming FIDL requests from a channel: {0}"
282 )]
283 ServerRequestRead(#[source] TransportError),
284
285 #[error("A FIDL server encountered an IO error writing an epitaph into a channel: {0}")]
286 ServerEpitaphWrite(#[source] TransportError),
287
288 #[error("A FIDL client encountered an IO error reading a response from a channel: {0}")]
289 ClientRead(#[source] TransportError),
290
291 #[error("A FIDL client encountered an IO error writing a request into a channel: {0}")]
292 ClientWrite(#[source] TransportError),
293
294 #[error("A FIDL client encountered an IO error issuing a channel call: {0}")]
295 ClientCall(#[source] Status),
296
297 #[error("A FIDL client encountered an IO error issuing a channel call: {0}")]
298 ClientEvent(#[source] Status),
299
300 #[cfg(not(target_os = "fuchsia"))]
301 #[error(
302 "A FIDL client's channel to the protocol {protocol_name} was closed: {epitaph}, reason: {}",
303 .reason.as_ref().map(String::as_str).unwrap_or("not given")
304 )]
305 ClientChannelClosed {
306 #[source]
308 epitaph: Epitaph,
309 protocol_name: &'static str,
311 reason: Option<String>,
313 },
314
315 #[cfg(target_os = "fuchsia")]
316 #[error("A FIDL client's channel to the protocol {protocol_name} was closed: {epitaph}")]
317 ClientChannelClosed {
318 #[source]
320 epitaph: Epitaph,
321 protocol_name: &'static str,
323 },
324
325 #[error("There was an error attaching a FIDL channel to the async executor: {0}")]
326 AsyncChannel(#[source] Status),
327
328 #[cfg(target_os = "fuchsia")]
329 #[cfg(test)]
330 #[error("Test Status: {0}")]
331 TestIo(#[source] Status),
332}
333
334impl Error {
335 pub fn is_closed(&self) -> bool {
337 matches!(self, Error::ClientChannelClosed { .. })
338 }
339}