1use std::mem;
8
9use {AsHandleRef, HandleBased, Handle, HandleRef, Signals, Status, Time};
10use {sys, ok};
11
12#[derive(Debug, Eq, PartialEq)]
17pub struct Port(Handle);
18impl_handle_based!(Port);
19
20#[derive(PartialEq, Eq, Debug)]
23pub struct Packet(sys::zx_port_packet_t);
24
25#[derive(Debug, Copy, Clone)]
27pub enum PacketContents {
28 User(UserPacket),
30 SignalOne(SignalPacket),
32 SignalRep(SignalPacket),
34
35 #[doc(hidden)]
36 __Nonexhaustive
37}
38
39#[derive(Debug, Copy, Clone)]
42pub struct UserPacket(sys::zx_packet_user_t);
43
44#[derive(Debug, Copy, Clone)]
47pub struct SignalPacket(sys::zx_packet_signal_t);
48
49impl Packet {
50 pub fn from_user_packet(key: u64, status: i32, user: UserPacket) -> Packet {
52 Packet(
53 sys::zx_port_packet_t {
54 key: key,
55 packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_USER,
56 status: status,
57 union: user.0,
58 }
59 )
60 }
61
62 pub fn key(&self) -> u64 {
64 self.0.key
65 }
66
67 pub fn status(&self) -> i32 {
70 self.0.status
71 }
72
73 pub fn contents(&self) -> PacketContents {
75 if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_USER {
76 PacketContents::User(UserPacket(self.0.union))
77 } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_ONE {
78 PacketContents::SignalOne(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) }))
79 } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_REP {
80 PacketContents::SignalRep(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) }))
81 } else {
82 panic!("unexpected packet type");
83 }
84 }
85}
86
87impl UserPacket {
88 pub fn from_u8_array(val: [u8; 32]) -> UserPacket {
89 UserPacket(val)
90 }
91
92 pub fn as_u8_array(&self) -> &[u8; 32] {
93 &self.0
94 }
95
96 pub fn as_mut_u8_array(&mut self) -> &mut [u8; 32] {
97 &mut self.0
98 }
99}
100
101impl SignalPacket {
102 pub fn trigger(&self) -> Signals {
104 Signals::from_bits_truncate(self.0.trigger)
105 }
106
107 pub fn observed(&self) -> Signals {
109 Signals::from_bits_truncate(self.0.observed)
110 }
111
112 pub fn count(&self) -> u64 {
114 self.0.count
115 }
116}
117
118impl Port {
119 pub fn create() -> Result<Port, Status> {
125 unsafe {
126 let mut handle = 0;
127 let opts = 0;
128 let status = sys::zx_port_create(opts, &mut handle);
129 ok(status)?;
130 Ok(Handle::from_raw(handle).into())
131 }
132 }
133
134 pub fn queue(&self, packet: &Packet) -> Result<(), Status> {
140 let status = unsafe {
141 sys::zx_port_queue(self.raw_handle(),
142 &packet.0 as *const sys::zx_port_packet_t, 0)
143 };
144 ok(status)
145 }
146
147 pub fn wait(&self, deadline: Time) -> Result<Packet, Status> {
153 let mut packet = Default::default();
154 let status = unsafe {
155 sys::zx_port_wait(self.raw_handle(), deadline.nanos(),
156 &mut packet as *mut sys::zx_port_packet_t, 0)
157 };
158 ok(status)?;
159 Ok(Packet(packet))
160 }
161
162 pub fn cancel<H>(&self, source: &H, key: u64) -> Result<(), Status> where H: HandleBased {
168 let status = unsafe {
169 sys::zx_port_cancel(self.raw_handle(), source.raw_handle(), key)
170 };
171 ok(status)
172 }
173}
174
175#[repr(u32)]
177#[derive(Debug, Copy, Clone, Eq, PartialEq)]
178pub enum WaitAsyncOpts {
179 Once = sys::ZX_WAIT_ASYNC_ONCE,
180 Repeating = sys::ZX_WAIT_ASYNC_REPEATING,
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186 use {DurationNum, Event};
187
188 #[test]
189 fn port_basic() {
190 let ten_ms = 10.millis();
191
192 let port = Port::create().unwrap();
193
194 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
196
197 let packet = Packet::from_user_packet(
199 42,
200 123,
201 UserPacket::from_u8_array([13; 32]),
202 );
203 assert!(port.queue(&packet).is_ok());
204
205 let read_packet = port.wait(ten_ms.after_now()).unwrap();
207 assert_eq!(read_packet, packet);
208 }
209
210 #[test]
211 fn wait_async_once() {
212 let ten_ms = 10.millis();
213 let key = 42;
214
215 let port = Port::create().unwrap();
216 let event = Event::create().unwrap();
217
218 assert!(event.wait_async_handle(&port, key, Signals::USER_0 | Signals::USER_1,
219 WaitAsyncOpts::Once).is_ok());
220
221 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
223
224 assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
226 let read_packet = port.wait(ten_ms.after_now()).unwrap();
227 assert_eq!(read_packet.key(), key);
228 assert_eq!(read_packet.status(), 0);
229 match read_packet.contents() {
230 PacketContents::SignalOne(sig) => {
231 assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1);
232 assert_eq!(sig.observed(), Signals::USER_0);
233 assert_eq!(sig.count(), 1);
234 }
235 _ => panic!("wrong packet type"),
236 }
237
238 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
240
241 assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok());
243 let read_packet = port.wait(ten_ms.after_now()).unwrap();
244 assert_eq!(read_packet.key(), key);
245 assert_eq!(read_packet.status(), 0);
246 match read_packet.contents() {
247 PacketContents::SignalOne(sig) => {
248 assert_eq!(sig.trigger(), Signals::USER_0);
249 assert_eq!(sig.observed(), Signals::USER_0);
250 assert_eq!(sig.count(), 1);
251 }
252 _ => panic!("wrong packet type"),
253 }
254
255 assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok());
258 assert!(port.cancel(&event, key).is_ok());
259 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
260
261 assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok());
264 assert!(port.cancel(&event, key).is_ok());
265 assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
266 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
267 }
268
269 #[test]
270 fn wait_async_repeating() {
271 let ten_ms = 10.millis();
272 let key = 42;
273
274 let port = Port::create().unwrap();
275 let event = Event::create().unwrap();
276
277 assert!(event.wait_async_handle(&port, key, Signals::USER_0 | Signals::USER_1,
278 WaitAsyncOpts::Repeating).is_ok());
279
280 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
282
283 assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
285 let read_packet = port.wait(ten_ms.after_now()).unwrap();
286 assert_eq!(read_packet.key(), key);
287 assert_eq!(read_packet.status(), 0);
288 match read_packet.contents() {
289 PacketContents::SignalRep(sig) => {
290 assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1);
291 assert_eq!(sig.observed(), Signals::USER_0);
292 assert_eq!(sig.count(), 1);
293 }
294 _ => panic!("wrong packet type"),
295 }
296
297 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
300
301 assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
305 let read_packet = port.wait(ten_ms.after_now()).unwrap();
306 assert_eq!(read_packet.key(), key);
307 assert_eq!(read_packet.status(), 0);
308 match read_packet.contents() {
309 PacketContents::SignalRep(sig) => {
310 assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1);
311 assert_eq!(sig.observed(), Signals::USER_0);
312 assert_eq!(sig.count(), 1);
313 }
314 _ => panic!("wrong packet type"),
315 }
316
317 assert!(port.cancel(&event, key).is_ok());
319 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
320 assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok());
323 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
324
325 assert!(event.wait_async_handle(
327 &port, key, Signals::USER_0, WaitAsyncOpts::Repeating).is_ok());
328 let read_packet = port.wait(ten_ms.after_now()).unwrap();
329 assert_eq!(read_packet.key(), key);
330 assert_eq!(read_packet.status(), 0);
331 match read_packet.contents() {
332 PacketContents::SignalRep(sig) => {
333 assert_eq!(sig.trigger(), Signals::USER_0);
334 assert_eq!(sig.observed(), Signals::USER_0);
335 assert_eq!(sig.count(), 1);
336 }
337 _ => panic!("wrong packet type"),
338 }
339
340 drop(event);
342 assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT));
343 }
344}