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 $(#[$attr])*
30 $value => Some(stringify!($name)),
31 )*
32 _ => None,
33 }
34 }
35 }
36
37 impl ::std::fmt::Debug for $typename {
38 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
39 f.write_str(concat!(stringify!($typename), "("))?;
40 match self.assoc_const_name() {
41 Some(name) => f.write_str(&name)?,
42 None => ::std::fmt::Debug::fmt(&self.0, f)?,
43 }
44 f.write_str(")")
45 }
46 }
47 }
48}
49
50#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
57#[repr(transparent)]
58pub struct Status(sys::zx_status_t);
59impl Status {
60 pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> {
63 if raw == Status::OK.0 {
64 Ok(())
65 } else {
66 Err(Status(raw))
67 }
68 }
69
70 pub fn from_raw(raw: sys::zx_status_t) -> Self {
71 Status(raw)
72 }
73
74 pub fn into_raw(self) -> sys::zx_status_t {
75 self.0
76 }
77}
78
79pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> {
81 Status::ok(raw)
82}
83
84assoc_values!(Status, [
85 OK = sys::ZX_OK;
86 INTERNAL = sys::ZX_ERR_INTERNAL;
87 NOT_SUPPORTED = sys::ZX_ERR_NOT_SUPPORTED;
88 NO_RESOURCES = sys::ZX_ERR_NO_RESOURCES;
89 NO_MEMORY = sys::ZX_ERR_NO_MEMORY;
90 INTERRUPTED_RETRY = sys::ZX_ERR_INTERRUPTED_RETRY;
91 INVALID_ARGS = sys::ZX_ERR_INVALID_ARGS;
92 BAD_HANDLE = sys::ZX_ERR_BAD_HANDLE;
93 WRONG_TYPE = sys::ZX_ERR_WRONG_TYPE;
94 BAD_SYSCALL = sys::ZX_ERR_BAD_SYSCALL;
95 OUT_OF_RANGE = sys::ZX_ERR_OUT_OF_RANGE;
96 BUFFER_TOO_SMALL = sys::ZX_ERR_BUFFER_TOO_SMALL;
97 BAD_STATE = sys::ZX_ERR_BAD_STATE;
98 TIMED_OUT = sys::ZX_ERR_TIMED_OUT;
99 SHOULD_WAIT = sys::ZX_ERR_SHOULD_WAIT;
100 CANCELED = sys::ZX_ERR_CANCELED;
101 PEER_CLOSED = sys::ZX_ERR_PEER_CLOSED;
102 NOT_FOUND = sys::ZX_ERR_NOT_FOUND;
103 ALREADY_EXISTS = sys::ZX_ERR_ALREADY_EXISTS;
104 ALREADY_BOUND = sys::ZX_ERR_ALREADY_BOUND;
105 UNAVAILABLE = sys::ZX_ERR_UNAVAILABLE;
106 ACCESS_DENIED = sys::ZX_ERR_ACCESS_DENIED;
107 IO = sys::ZX_ERR_IO;
108 IO_REFUSED = sys::ZX_ERR_IO_REFUSED;
109 IO_DATA_INTEGRITY = sys::ZX_ERR_IO_DATA_INTEGRITY;
110 IO_DATA_LOSS = sys::ZX_ERR_IO_DATA_LOSS;
111 IO_NOT_PRESENT = sys::ZX_ERR_IO_NOT_PRESENT;
112 IO_OVERRUN = sys::ZX_ERR_IO_OVERRUN;
113 IO_MISSED_DEADLINE = sys::ZX_ERR_IO_MISSED_DEADLINE;
114 IO_INVALID = sys::ZX_ERR_IO_INVALID;
115 BAD_PATH = sys::ZX_ERR_BAD_PATH;
116 NOT_DIR = sys::ZX_ERR_NOT_DIR;
117 NOT_FILE = sys::ZX_ERR_NOT_FILE;
118 FILE_BIG = sys::ZX_ERR_FILE_BIG;
119 NO_SPACE = sys::ZX_ERR_NO_SPACE;
120 NOT_EMPTY = sys::ZX_ERR_NOT_EMPTY;
121 STOP = sys::ZX_ERR_STOP;
122 NEXT = sys::ZX_ERR_NEXT;
123 ASYNC = sys::ZX_ERR_ASYNC;
124 PROTOCOL_NOT_SUPPORTED = sys::ZX_ERR_PROTOCOL_NOT_SUPPORTED;
125 ADDRESS_UNREACHABLE = sys::ZX_ERR_ADDRESS_UNREACHABLE;
126 ADDRESS_IN_USE = sys::ZX_ERR_ADDRESS_IN_USE;
127 NOT_CONNECTED = sys::ZX_ERR_NOT_CONNECTED;
128 CONNECTION_REFUSED = sys::ZX_ERR_CONNECTION_REFUSED;
129 CONNECTION_RESET = sys::ZX_ERR_CONNECTION_RESET;
130 CONNECTION_ABORTED = sys::ZX_ERR_CONNECTION_ABORTED;
131]);
132
133impl Status {
134 pub fn into_io_error(self) -> io::Error {
135 self.into()
136 }
137
138 pub fn from_result(res: Result<(), Self>) -> Self {
139 res.into()
140 }
141}
142
143impl From<io::ErrorKind> for Status {
144 fn from(kind: io::ErrorKind) -> Self {
145 use std::io::ErrorKind::*;
146 match kind {
147 NotFound => Status::NOT_FOUND,
148 PermissionDenied => Status::ACCESS_DENIED,
149 ConnectionRefused => Status::IO_REFUSED,
150 ConnectionAborted => Status::PEER_CLOSED,
151 AddrInUse => Status::ALREADY_BOUND,
152 AddrNotAvailable => Status::UNAVAILABLE,
153 BrokenPipe => Status::PEER_CLOSED,
154 AlreadyExists => Status::ALREADY_EXISTS,
155 WouldBlock => Status::SHOULD_WAIT,
156 InvalidInput => Status::INVALID_ARGS,
157 TimedOut => Status::TIMED_OUT,
158 Interrupted => Status::INTERRUPTED_RETRY,
159 UnexpectedEof | WriteZero | ConnectionReset | NotConnected | Other | _ => Status::IO,
160 }
161 }
162}
163
164impl From<Status> for io::ErrorKind {
165 fn from(status: Status) -> io::ErrorKind {
166 use std::io::ErrorKind::*;
167 match status {
168 Status::INTERRUPTED_RETRY => Interrupted,
169 Status::BAD_HANDLE => BrokenPipe,
170 Status::TIMED_OUT => TimedOut,
171 Status::SHOULD_WAIT => WouldBlock,
172 Status::PEER_CLOSED => ConnectionAborted,
173 Status::NOT_FOUND => NotFound,
174 Status::ALREADY_EXISTS => AlreadyExists,
175 Status::ALREADY_BOUND => AlreadyExists,
176 Status::UNAVAILABLE => AddrNotAvailable,
177 Status::ACCESS_DENIED => PermissionDenied,
178 Status::IO_REFUSED => ConnectionRefused,
179 Status::IO_DATA_INTEGRITY => InvalidData,
180
181 Status::BAD_PATH | Status::INVALID_ARGS | Status::OUT_OF_RANGE | Status::WRONG_TYPE => {
182 InvalidInput
183 }
184
185 Status::OK
186 | Status::NEXT
187 | Status::STOP
188 | Status::NO_SPACE
189 | Status::FILE_BIG
190 | Status::NOT_FILE
191 | Status::NOT_DIR
192 | Status::IO_DATA_LOSS
193 | Status::IO
194 | Status::CANCELED
195 | Status::BAD_STATE
196 | Status::BUFFER_TOO_SMALL
197 | Status::BAD_SYSCALL
198 | Status::INTERNAL
199 | Status::NOT_SUPPORTED
200 | Status::NO_RESOURCES
201 | Status::NO_MEMORY
202 | _ => Other,
203 }
204 }
205}
206
207impl fmt::Display for Status {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 match self.assoc_const_name() {
210 Some(name) => name.fmt(f),
211 None => write!(f, "Unknown zircon status code: {}", self.0),
212 }
213 }
214}
215
216impl error::Error for Status {}
217
218impl From<io::Error> for Status {
219 fn from(err: io::Error) -> Status {
220 err.kind().into()
221 }
222}
223
224impl From<Status> for io::Error {
225 fn from(status: Status) -> io::Error {
226 io::Error::from(io::ErrorKind::from(status))
227 }
228}
229
230impl From<NulError> for Status {
231 fn from(_error: NulError) -> Status {
232 Status::INVALID_ARGS
233 }
234}
235
236impl From<Result<(), Status>> for Status {
237 fn from(res: Result<(), Status>) -> Status {
238 match res {
239 Ok(()) => Self::OK,
240 Err(status) => status,
241 }
242 }
243}
244
245impl From<Status> for Result<(), Status> {
246 fn from(src: Status) -> Result<(), Status> {
247 Status::ok(src.into_raw())
248 }
249}
250
251#[cfg(test)]
252mod test {
253 use super::Status;
254
255 #[test]
256 fn status_debug_format() {
257 let cases = [
258 ("Status(OK)", Status::OK),
259 ("Status(BAD_SYSCALL)", Status::BAD_SYSCALL),
260 ("Status(NEXT)", Status::NEXT),
261 ("Status(-5050)", Status(-5050)),
262 ];
263 for &(expected, value) in &cases {
264 assert_eq!(expected, format!("{:?}", value));
265 }
266 }
267
268 #[test]
269 fn status_into_result() {
270 let ok_result: Result<(), Status> = Status::OK.into();
271 assert_eq!(ok_result, Ok(()));
272
273 let err_result: Result<(), Status> = Status::BAD_SYSCALL.into();
274 assert_eq!(err_result, Err(Status::BAD_SYSCALL));
275 }
276}