1#![deny(warnings)]
9
10#[macro_use]
11extern crate bitflags;
12
13pub extern crate fuchsia_zircon_sys as sys;
14
15#[deprecated(note="use fuchsia_zircon::sys::ZX_CPRNG_DRAW_MAX_LEN instead")]
16#[doc(hidden)]
17pub use sys::ZX_CPRNG_DRAW_MAX_LEN;
18
19macro_rules! impl_handle_based {
21 ($type_name:path) => {
22 impl AsHandleRef for $type_name {
23 fn as_handle_ref(&self) -> HandleRef {
24 self.0.as_handle_ref()
25 }
26 }
27
28 impl From<Handle> for $type_name {
29 fn from(handle: Handle) -> Self {
30 $type_name(handle)
31 }
32 }
33
34 impl From<$type_name> for Handle {
35 fn from(x: $type_name) -> Handle {
36 x.0
37 }
38 }
39
40 impl HandleBased for $type_name {}
41 }
42}
43
44macro_rules! assoc_consts {
47 ($typename:ident, [$($name:ident = $num:expr;)*]) => {
48 #[allow(non_upper_case_globals)]
49 impl $typename {
50 $(
51 pub const $name: $typename = $typename($num);
52 )*
53 }
54 }
55}
56
57mod channel;
58mod cprng;
59mod event;
60mod eventpair;
61mod fifo;
62mod handle;
63mod job;
64mod port;
65mod process;
66mod rights;
67mod socket;
68mod signals;
69mod status;
70mod time;
71mod thread;
72mod vmar;
73mod vmo;
74
75pub use channel::*;
76pub use cprng::*;
77pub use event::*;
78pub use eventpair::*;
79pub use fifo::*;
80pub use handle::*;
81pub use job::*;
82pub use port::*;
83pub use process::*;
84pub use rights::*;
85pub use socket::*;
86pub use signals::*;
87pub use status::*;
88pub use thread::*;
89pub use time::*;
90pub use vmar::*;
91pub use vmo::*;
92
93pub mod prelude {
96 pub use {
97 AsHandleRef,
98 Cookied,
99 DurationNum,
100 HandleBased,
101 Peered,
102 };
103}
104
105pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> {
107 Status::ok(raw)
108}
109
110#[repr(C)]
113#[derive(Debug)]
114pub struct WaitItem<'a> {
115 pub handle: HandleRef<'a>,
117 pub waitfor: Signals,
119 pub pending: Signals,
121}
122
123#[repr(u32)]
127#[derive(Debug, Copy, Clone, Eq, PartialEq)]
128pub enum ClockId {
129 Monotonic = 0,
132 UTC = 1,
135 Thread = 2,
138}
139
140pub fn object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result<bool, Status>
148{
149 let len = try!(usize_into_u32(items.len()).map_err(|_| Status::OUT_OF_RANGE));
150 let items_ptr = items.as_mut_ptr() as *mut sys::zx_wait_item_t;
151 let status = unsafe { sys::zx_object_wait_many( items_ptr, len, deadline.nanos()) };
152 if status == sys::ZX_ERR_CANCELED {
153 return Ok(true)
154 }
155 ok(status).map(|()| false)
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 #[allow(unused_imports)]
162 use super::prelude::*;
163
164 #[test]
165 fn monotonic_time_increases() {
166 let time1 = Time::get(ClockId::Monotonic);
167 1_000.nanos().sleep();
168 let time2 = Time::get(ClockId::Monotonic);
169 assert!(time2 > time1);
170 }
171
172 #[test]
173 fn utc_time_increases() {
174 let time1 = Time::get(ClockId::UTC);
175 1_000.nanos().sleep();
176 let time2 = Time::get(ClockId::UTC);
177 assert!(time2 > time1);
178 }
179
180 #[test]
181 fn thread_time_increases() {
182 let time1 = Time::get(ClockId::Thread);
183 1_000.nanos().sleep();
184 let time2 = Time::get(ClockId::Thread);
185 assert!(time2 > time1);
186 }
187
188 #[test]
189 fn ticks_increases() {
190 let ticks1 = ticks_get();
191 1_000.nanos().sleep();
192 let ticks2 = ticks_get();
193 assert!(ticks2 > ticks1);
194 }
195
196 #[test]
197 fn tick_length() {
198 let sleep_time = 1.milli();
199 let ticks1 = ticks_get();
200 sleep_time.sleep();
201 let ticks2 = ticks_get();
202
203 let sleep_ticks = sleep_time.millis() * ticks_per_second() / 1000;
205 assert!(ticks2 >= (ticks1 + sleep_ticks));
206 }
207
208 #[test]
209 fn into_raw() {
210 let vmo = Vmo::create(1).unwrap();
211 let h = vmo.into_raw();
212 let vmo2 = Vmo::from(unsafe { Handle::from_raw(h) });
213 assert!(vmo2.write(b"1", 0).is_ok());
214 }
215
216 #[test]
217 fn sleep() {
218 let sleep_ns = 1.millis();
219 let time1 = Time::get(ClockId::Monotonic);
220 sleep_ns.sleep();
221 let time2 = Time::get(ClockId::Monotonic);
222 assert!(time2 > time1 + sleep_ns);
223 }
224
225 #[test]
227 fn duplicate() {
228 let hello_length: usize = 5;
229
230 let vmo = Vmo::create(hello_length as u64).unwrap();
232 assert!(vmo.write(b"hello", 0).is_ok());
233
234 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
236 let mut read_vec = vec![0; hello_length];
238 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
239 assert_eq!(read_vec, b"hello");
240 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
241
242 assert!(vmo.write(b"bye", 0).is_ok());
244 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
245 assert_eq!(read_vec, b"byelo");
246 }
247
248 #[test]
250 fn replace() {
251 let hello_length: usize = 5;
252
253 let vmo = Vmo::create(hello_length as u64).unwrap();
255 assert!(vmo.write(b"hello", 0).is_ok());
256
257 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
259 let mut read_vec = vec![0; hello_length];
261 assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
262 assert_eq!(read_vec, b"hello");
263 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
264 }
265
266 #[test]
267 fn wait_and_signal() {
268 let event = Event::create().unwrap();
269 let ten_ms = 10.millis();
270
271 assert_eq!(event.wait_handle(
273 Signals::USER_0, ten_ms.after_now()), Err(Status::TIMED_OUT));
274
275 assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
277 assert_eq!(event.wait_handle(Signals::USER_0, ten_ms.after_now()).unwrap(),
278 Signals::USER_0);
279
280 assert_eq!(event.wait_handle(Signals::USER_0, ten_ms.after_now()).unwrap(),
282 Signals::USER_0);
283
284 assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok());
286 assert_eq!(event.wait_handle(
287 Signals::USER_0, ten_ms.after_now()), Err(Status::TIMED_OUT));
288 }
289
290 #[test]
291 fn wait_many_and_signal() {
292 let ten_ms = 10.millis();
293 let e1 = Event::create().unwrap();
294 let e2 = Event::create().unwrap();
295
296 let mut items = vec![
298 WaitItem { handle: e1.as_handle_ref(), waitfor: Signals::USER_0, pending: Signals::NONE },
299 WaitItem { handle: e2.as_handle_ref(), waitfor: Signals::USER_1, pending: Signals::NONE },
300 ];
301 assert_eq!(object_wait_many(&mut items, ten_ms.after_now()), Err(Status::TIMED_OUT));
302 assert_eq!(items[0].pending, Signals::NONE);
303 assert_eq!(items[1].pending, Signals::NONE);
304
305 assert!(e1.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
307 assert!(object_wait_many(&mut items, ten_ms.after_now()).is_ok());
308 assert_eq!(items[0].pending, Signals::USER_0);
309 assert_eq!(items[1].pending, Signals::NONE);
310
311 assert!(e2.signal_handle(Signals::NONE, Signals::USER_1).is_ok());
313 assert!(object_wait_many(&mut items, ten_ms.after_now()).is_ok());
314 assert_eq!(items[0].pending, Signals::USER_0);
315 assert_eq!(items[1].pending, Signals::USER_1);
316
317 assert!(e1.signal_handle(Signals::USER_0, Signals::NONE).is_ok());
319 assert!(e2.signal_handle(Signals::USER_1, Signals::NONE).is_ok());
320 assert_eq!(object_wait_many(&mut items, ten_ms.after_now()), Err(Status::TIMED_OUT));
321 assert_eq!(items[0].pending, Signals::NONE);
322 assert_eq!(items[1].pending, Signals::NONE);
323 }
324
325 #[test]
326 fn cookies() {
327 let event = Event::create().unwrap();
328 let scope = Event::create().unwrap();
329
330 assert_eq!(event.get_cookie(&scope.as_handle_ref()), Err(Status::ACCESS_DENIED));
332
333 assert_eq!(event.set_cookie(&scope.as_handle_ref(), 42), Ok(()));
335
336 assert_eq!(event.get_cookie(&scope.as_handle_ref()), Ok(42));
338
339 assert_eq!(event.get_cookie(&event.as_handle_ref()), Err(Status::ACCESS_DENIED));
341
342 assert_eq!(event.set_cookie(&scope.as_handle_ref(), 123), Ok(()));
344
345 assert_eq!(event.set_cookie(&event.as_handle_ref(), 123), Err(Status::ACCESS_DENIED));
347 }
348}
349
350pub fn usize_into_u32(n: usize) -> Result<u32, ()> {
351 if n > ::std::u32::MAX as usize || n < ::std::u32::MIN as usize {
352 return Err(())
353 }
354 Ok(n as u32)
355}
356
357pub fn size_to_u32_sat(n: usize) -> u32 {
358 if n > ::std::u32::MAX as usize {
359 return ::std::u32::MAX;
360 }
361 if n < ::std::u32::MIN as usize {
362 return ::std::u32::MIN;
363 }
364 n as u32
365}