1use std::ffi::NulError;
8use std::{error, fmt, io};
9use zx_types as sys;
10
11#[macro_export]
17macro_rules! assoc_values {
18 ($typename:ident, [$($(#[$attr:meta])* $name:ident = $value:path;)*]) => {
19 #[allow(non_upper_case_globals)]
20 impl $typename {
21 $(
22 $(#[$attr])*
23 pub const $name: $typename = $typename($value);
24 )*
25
26 fn assoc_const_name(&self) -> Option<&'static str> {
27 match self.0 {
28 $(
29 $value => Some(stringify!($name)),
30 )*
31 _ => None,
32 }
33 }
34 }
35
36 impl ::std::fmt::Debug for $typename {
37 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
38 f.write_str(concat!(stringify!($typename), "("))?;
39 match self.assoc_const_name() {
40 Some(name) => f.write_str(&name)?,
41 None => ::std::fmt::Debug::fmt(&self.0, f)?,
42 }
43 f.write_str(")")
44 }
45 }
46 }
47}
48
49#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
56#[repr(transparent)]
57pub struct Status(sys::zx_status_t);
58impl Status {
59 pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> {
62 if raw == Status::OK.0 { Ok(()) } else { Err(Status(raw)) }
63 }
64
65 pub fn from_raw(raw: sys::zx_status_t) -> Self {
66 Status(raw)
67 }
68
69 pub fn into_raw(self) -> sys::zx_status_t {
70 self.0
71 }
72}
73
74pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> {
76 Status::ok(raw)
77}
78
79assoc_values!(Status, [
81 #[doc = "Indicates an operation was successful."]
82 OK = sys::ZX_OK;
83 #[doc = "The system encountered an otherwise unspecified error while performing the"]
84 #[doc = "operation."]
85 INTERNAL = sys::ZX_ERR_INTERNAL;
86 #[doc = "The operation is not implemented, supported, or enabled."]
87 NOT_SUPPORTED = sys::ZX_ERR_NOT_SUPPORTED;
88 #[doc = "The system was not able to allocate some resource needed for the operation."]
89 NO_RESOURCES = sys::ZX_ERR_NO_RESOURCES;
90 #[doc = "The system was not able to allocate memory needed for the operation."]
91 NO_MEMORY = sys::ZX_ERR_NO_MEMORY;
92 #[doc = "The system call was interrupted, but should be retried. This should not be"]
93 #[doc = "seen outside of the VDSO."]
94 INTERRUPTED_RETRY = sys::ZX_ERR_INTERRUPTED_RETRY;
95 #[doc = "An argument is invalid. For example, a null pointer when a null pointer is"]
96 #[doc = "not permitted."]
97 INVALID_ARGS = sys::ZX_ERR_INVALID_ARGS;
98 #[doc = "A specified handle value does not refer to a handle."]
99 BAD_HANDLE = sys::ZX_ERR_BAD_HANDLE;
100 #[doc = "The subject of the operation is the wrong type to perform the operation."]
101 #[doc = ""]
102 #[doc = "For example: Attempting a message_read on a thread handle."]
103 WRONG_TYPE = sys::ZX_ERR_WRONG_TYPE;
104 #[doc = "The specified syscall number is invalid."]
105 BAD_SYSCALL = sys::ZX_ERR_BAD_SYSCALL;
106 #[doc = "An argument is outside the valid range for this operation."]
107 OUT_OF_RANGE = sys::ZX_ERR_OUT_OF_RANGE;
108 #[doc = "The caller-provided buffer is too small for this operation."]
109 BUFFER_TOO_SMALL = sys::ZX_ERR_BUFFER_TOO_SMALL;
110 #[doc = "The operation failed because the current state of the object does not allow"]
111 #[doc = "it, or a precondition of the operation is not satisfied."]
112 BAD_STATE = sys::ZX_ERR_BAD_STATE;
113 #[doc = "The time limit for the operation elapsed before the operation completed."]
114 TIMED_OUT = sys::ZX_ERR_TIMED_OUT;
115 #[doc = "The operation cannot be performed currently but potentially could succeed if"]
116 #[doc = "the caller waits for a prerequisite to be satisfied, like waiting for a"]
117 #[doc = "handle to be readable or writable."]
118 #[doc = ""]
119 #[doc = "Example: Attempting to read from a channel that has no messages waiting but"]
120 #[doc = "has an open remote will return `ZX_ERR_SHOULD_WAIT`. In contrast, attempting"]
121 #[doc = "to read from a channel that has no messages waiting and has a closed remote"]
122 #[doc = "end will return `ZX_ERR_PEER_CLOSED`."]
123 SHOULD_WAIT = sys::ZX_ERR_SHOULD_WAIT;
124 #[doc = "The in-progress operation, for example, a wait, has been canceled."]
125 CANCELED = sys::ZX_ERR_CANCELED;
126 #[doc = "The operation failed because the remote end of the subject of the operation"]
127 #[doc = "was closed."]
128 PEER_CLOSED = sys::ZX_ERR_PEER_CLOSED;
129 #[doc = "The requested entity is not found."]
130 NOT_FOUND = sys::ZX_ERR_NOT_FOUND;
131 #[doc = "An object with the specified identifier already exists."]
132 #[doc = ""]
133 #[doc = "Example: Attempting to create a file when a file already exists with that"]
134 #[doc = "name."]
135 ALREADY_EXISTS = sys::ZX_ERR_ALREADY_EXISTS;
136 #[doc = "The operation failed because the named entity is already owned or controlled"]
137 #[doc = "by another entity. The operation could succeed later if the current owner"]
138 #[doc = "releases the entity."]
139 ALREADY_BOUND = sys::ZX_ERR_ALREADY_BOUND;
140 #[doc = "The subject of the operation is currently unable to perform the operation."]
141 #[doc = ""]
142 #[doc = "This is used when there's no direct way for the caller to observe when the"]
143 #[doc = "subject will be able to perform the operation and should thus retry."]
144 UNAVAILABLE = sys::ZX_ERR_UNAVAILABLE;
145 #[doc = "The caller did not have permission to perform the specified operation."]
146 ACCESS_DENIED = sys::ZX_ERR_ACCESS_DENIED;
147 #[doc = "Otherwise-unspecified error occurred during I/O."]
148 IO = sys::ZX_ERR_IO;
149 #[doc = "The entity the I/O operation is being performed on rejected the operation."]
150 #[doc = ""]
151 #[doc = "Example: an I2C device NAK'ing a transaction or a disk controller rejecting"]
152 #[doc = "an invalid command, or a stalled USB endpoint."]
153 IO_REFUSED = sys::ZX_ERR_IO_REFUSED;
154 #[doc = "The data in the operation failed an integrity check and is possibly"]
155 #[doc = "corrupted."]
156 #[doc = ""]
157 #[doc = "Example: CRC or Parity error."]
158 IO_DATA_INTEGRITY = sys::ZX_ERR_IO_DATA_INTEGRITY;
159 #[doc = "The data in the operation is currently unavailable and may be permanently"]
160 #[doc = "lost."]
161 #[doc = ""]
162 #[doc = "Example: A disk block is irrecoverably damaged."]
163 IO_DATA_LOSS = sys::ZX_ERR_IO_DATA_LOSS;
164 #[doc = "The device is no longer available (has been unplugged from the system,"]
165 #[doc = "powered down, or the driver has been unloaded)."]
166 IO_NOT_PRESENT = sys::ZX_ERR_IO_NOT_PRESENT;
167 #[doc = "More data was received from the device than expected."]
168 #[doc = ""]
169 #[doc = "Example: a USB \"babble\" error due to a device sending more data than the"]
170 #[doc = "host queued to receive."]
171 IO_OVERRUN = sys::ZX_ERR_IO_OVERRUN;
172 #[doc = "An operation did not complete within the required timeframe."]
173 #[doc = ""]
174 #[doc = "Example: A USB isochronous transfer that failed to complete due to an"]
175 #[doc = "overrun or underrun."]
176 IO_MISSED_DEADLINE = sys::ZX_ERR_IO_MISSED_DEADLINE;
177 #[doc = "The data in the operation is invalid parameter or is out of range."]
178 #[doc = ""]
179 #[doc = "Example: A USB transfer that failed to complete with TRB Error"]
180 IO_INVALID = sys::ZX_ERR_IO_INVALID;
181 #[doc = "Path name is too long."]
182 BAD_PATH = sys::ZX_ERR_BAD_PATH;
183 #[doc = "The object is not a directory or does not support directory operations."]
184 #[doc = ""]
185 #[doc = "Example: Attempted to open a file as a directory or attempted to do"]
186 #[doc = "directory operations on a file."]
187 NOT_DIR = sys::ZX_ERR_NOT_DIR;
188 #[doc = "Object is not a regular file."]
189 NOT_FILE = sys::ZX_ERR_NOT_FILE;
190 #[doc = "This operation would cause a file to exceed a filesystem-specific size"]
191 #[doc = "limit."]
192 FILE_BIG = sys::ZX_ERR_FILE_BIG;
193 #[doc = "The filesystem or device space is exhausted."]
194 NO_SPACE = sys::ZX_ERR_NO_SPACE;
195 #[doc = "The directory is not empty for an operation that requires it to be empty."]
196 #[doc = ""]
197 #[doc = "For example, non-recursively deleting a directory with files still in it."]
198 NOT_EMPTY = sys::ZX_ERR_NOT_EMPTY;
199 #[doc = "An indicate to not call again."]
200 #[doc = ""]
201 #[doc = "The flow control values `ZX_ERR_STOP`, `ZX_ERR_NEXT`, and `ZX_ERR_ASYNC` are"]
202 #[doc = "not errors and will never be returned by a system call or public API. They"]
203 #[doc = "allow callbacks to request their caller perform some other operation."]
204 #[doc = ""]
205 #[doc = "For example, a callback might be called on every event until it returns"]
206 #[doc = "something other than `ZX_OK`. This status allows differentiation between"]
207 #[doc = "\"stop due to an error\" and \"stop because work is done.\""]
208 STOP = sys::ZX_ERR_STOP;
209 #[doc = "Advance to the next item."]
210 #[doc = ""]
211 #[doc = "The flow control values `ZX_ERR_STOP`, `ZX_ERR_NEXT`, and `ZX_ERR_ASYNC` are"]
212 #[doc = "not errors and will never be returned by a system call or public API. They"]
213 #[doc = "allow callbacks to request their caller perform some other operation."]
214 #[doc = ""]
215 #[doc = "For example, a callback could use this value to indicate it did not consume"]
216 #[doc = "an item passed to it, but by choice, not due to an error condition."]
217 NEXT = sys::ZX_ERR_NEXT;
218 #[doc = "Ownership of the item has moved to an asynchronous worker."]
219 #[doc = ""]
220 #[doc = "The flow control values `ZX_ERR_STOP`, `ZX_ERR_NEXT`, and `ZX_ERR_ASYNC` are"]
221 #[doc = "not errors and will never be returned by a system call or public API. They"]
222 #[doc = "allow callbacks to request their caller perform some other operation."]
223 #[doc = ""]
224 #[doc = "Unlike `ZX_ERR_STOP`, which implies that iteration on an object"]
225 #[doc = "should stop, and `ZX_ERR_NEXT`, which implies that iteration"]
226 #[doc = "should continue to the next item, `ZX_ERR_ASYNC` implies"]
227 #[doc = "that an asynchronous worker is responsible for continuing iteration."]
228 #[doc = ""]
229 #[doc = "For example, a callback will be called on every event, but one event needs"]
230 #[doc = "to handle some work asynchronously before it can continue. `ZX_ERR_ASYNC`"]
231 #[doc = "implies the worker is responsible for resuming iteration once its work has"]
232 #[doc = "completed."]
233 ASYNC = sys::ZX_ERR_ASYNC;
234 #[doc = "The specified protocol is not supported."]
235 PROTOCOL_NOT_SUPPORTED = sys::ZX_ERR_PROTOCOL_NOT_SUPPORTED;
236 #[doc = "The host is unreachable."]
237 ADDRESS_UNREACHABLE = sys::ZX_ERR_ADDRESS_UNREACHABLE;
238 #[doc = "Address is being used by someone else."]
239 ADDRESS_IN_USE = sys::ZX_ERR_ADDRESS_IN_USE;
240 #[doc = "The socket is not connected."]
241 NOT_CONNECTED = sys::ZX_ERR_NOT_CONNECTED;
242 #[doc = "The remote peer rejected the connection."]
243 CONNECTION_REFUSED = sys::ZX_ERR_CONNECTION_REFUSED;
244 #[doc = "The connection was reset."]
245 CONNECTION_RESET = sys::ZX_ERR_CONNECTION_RESET;
246 #[doc = "The connection was aborted."]
247 CONNECTION_ABORTED = sys::ZX_ERR_CONNECTION_ABORTED;
248]);
249impl Status {
252 pub fn into_io_error(self) -> io::Error {
253 self.into()
254 }
255
256 pub fn from_result(res: Result<(), Self>) -> Self {
257 res.into()
258 }
259}
260
261impl From<io::ErrorKind> for Status {
262 fn from(kind: io::ErrorKind) -> Self {
263 use std::io::ErrorKind::*;
264 match kind {
265 NotFound => Status::NOT_FOUND,
266 PermissionDenied => Status::ACCESS_DENIED,
267 ConnectionRefused => Status::IO_REFUSED,
268 ConnectionAborted => Status::PEER_CLOSED,
269 AddrInUse => Status::ALREADY_BOUND,
270 AddrNotAvailable => Status::UNAVAILABLE,
271 BrokenPipe => Status::PEER_CLOSED,
272 AlreadyExists => Status::ALREADY_EXISTS,
273 WouldBlock => Status::SHOULD_WAIT,
274 InvalidInput => Status::INVALID_ARGS,
275 TimedOut => Status::TIMED_OUT,
276 Interrupted => Status::INTERRUPTED_RETRY,
277 UnexpectedEof | WriteZero | ConnectionReset | NotConnected | Other | _ => Status::IO,
278 }
279 }
280}
281
282impl From<Status> for io::ErrorKind {
283 fn from(status: Status) -> io::ErrorKind {
284 use std::io::ErrorKind::*;
285 match status {
286 Status::INTERRUPTED_RETRY => Interrupted,
287 Status::BAD_HANDLE => BrokenPipe,
288 Status::TIMED_OUT => TimedOut,
289 Status::SHOULD_WAIT => WouldBlock,
290 Status::PEER_CLOSED => ConnectionAborted,
291 Status::NOT_FOUND => NotFound,
292 Status::ALREADY_EXISTS => AlreadyExists,
293 Status::ALREADY_BOUND => AlreadyExists,
294 Status::UNAVAILABLE => AddrNotAvailable,
295 Status::ACCESS_DENIED => PermissionDenied,
296 Status::IO_REFUSED => ConnectionRefused,
297 Status::IO_DATA_INTEGRITY => InvalidData,
298
299 Status::BAD_PATH | Status::INVALID_ARGS | Status::OUT_OF_RANGE | Status::WRONG_TYPE => {
300 InvalidInput
301 }
302
303 Status::OK
304 | Status::NEXT
305 | Status::STOP
306 | Status::NO_SPACE
307 | Status::FILE_BIG
308 | Status::NOT_FILE
309 | Status::NOT_DIR
310 | Status::IO_DATA_LOSS
311 | Status::IO
312 | Status::CANCELED
313 | Status::BAD_STATE
314 | Status::BUFFER_TOO_SMALL
315 | Status::BAD_SYSCALL
316 | Status::INTERNAL
317 | Status::NOT_SUPPORTED
318 | Status::NO_RESOURCES
319 | Status::NO_MEMORY
320 | _ => Other,
321 }
322 }
323}
324
325impl fmt::Display for Status {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 match self.assoc_const_name() {
328 Some(name) => name.fmt(f),
329 None => write!(f, "Unknown zircon status code: {}", self.0),
330 }
331 }
332}
333
334impl error::Error for Status {}
335
336impl From<io::Error> for Status {
337 fn from(err: io::Error) -> Status {
338 err.kind().into()
339 }
340}
341
342impl From<Status> for io::Error {
343 fn from(status: Status) -> io::Error {
344 io::Error::from(io::ErrorKind::from(status))
345 }
346}
347
348impl From<NulError> for Status {
349 fn from(_error: NulError) -> Status {
350 Status::INVALID_ARGS
351 }
352}
353
354impl From<Result<(), Status>> for Status {
355 fn from(res: Result<(), Status>) -> Status {
356 match res {
357 Ok(()) => Self::OK,
358 Err(status) => status,
359 }
360 }
361}
362
363impl From<Status> for Result<(), Status> {
364 fn from(src: Status) -> Result<(), Status> {
365 Status::ok(src.into_raw())
366 }
367}
368
369#[cfg(test)]
370mod test {
371 use super::Status;
372
373 #[test]
374 fn status_debug_format() {
375 let cases = [
376 ("Status(OK)", Status::OK),
377 ("Status(BAD_SYSCALL)", Status::BAD_SYSCALL),
378 ("Status(NEXT)", Status::NEXT),
379 ("Status(-5050)", Status(-5050)),
380 ];
381 for &(expected, value) in &cases {
382 assert_eq!(expected, format!("{:?}", value));
383 }
384 }
385
386 #[test]
387 fn status_into_result() {
388 let ok_result: Result<(), Status> = Status::OK.into();
389 assert_eq!(ok_result, Ok(()));
390
391 let err_result: Result<(), Status> = Status::BAD_SYSCALL.into();
392 assert_eq!(err_result, Err(Status::BAD_SYSCALL));
393 }
394}