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