1use super::rwhandle::{RWHandle, ReadableHandle as _, WritableHandle as _};
6use futures::ready;
7use std::fmt;
8use std::future::poll_fn;
9use std::mem::MaybeUninit;
10use std::num::NonZeroUsize;
11use std::task::{Context, Poll};
12use zerocopy::{FromBytes, Immutable, IntoBytes};
13use zx::{self as zx, AsHandleRef};
14
15pub trait FifoEntry: IntoBytes + FromBytes + Immutable {}
20
21impl<O: IntoBytes + FromBytes + Immutable> FifoEntry for O {}
22
23pub trait FifoWriteBuffer<T> {
25 fn as_slice(&self) -> &[T];
26}
27
28pub unsafe trait FifoReadBuffer<T> {
36 fn count(&self) -> usize;
38 fn as_mut_ptr(&mut self) -> *mut T;
46}
47
48impl<T: FifoEntry, const N: usize> FifoWriteBuffer<T> for [T; N] {
49 fn as_slice(&self) -> &[T] {
50 self
51 }
52}
53
54impl<T: FifoEntry> FifoWriteBuffer<T> for [T] {
55 fn as_slice(&self) -> &[T] {
56 self
57 }
58}
59
60unsafe impl<T: FifoEntry, const N: usize> FifoReadBuffer<T> for [T; N] {
61 fn count(&self) -> usize {
62 N
63 }
64
65 fn as_mut_ptr(&mut self) -> *mut T {
66 self.as_mut_slice().as_mut_ptr()
67 }
68}
69
70unsafe impl<T: FifoEntry> FifoReadBuffer<T> for [T] {
71 fn count(&self) -> usize {
72 self.len()
73 }
74
75 fn as_mut_ptr(&mut self) -> *mut T {
76 self.as_mut_ptr()
77 }
78}
79
80impl<T: FifoEntry> FifoWriteBuffer<T> for T {
81 fn as_slice(&self) -> &[T] {
82 std::slice::from_ref(self)
83 }
84}
85
86unsafe impl<T: FifoEntry> FifoReadBuffer<T> for T {
87 fn count(&self) -> usize {
88 1
89 }
90
91 fn as_mut_ptr(&mut self) -> *mut T {
92 self as *mut T
93 }
94}
95
96unsafe impl<T: FifoEntry> FifoReadBuffer<T> for MaybeUninit<T> {
97 fn count(&self) -> usize {
98 1
99 }
100
101 fn as_mut_ptr(&mut self) -> *mut T {
102 self.as_mut_ptr()
103 }
104}
105
106unsafe impl<T: FifoEntry> FifoReadBuffer<T> for [MaybeUninit<T>] {
107 fn count(&self) -> usize {
108 self.len()
109 }
110
111 fn as_mut_ptr(&mut self) -> *mut T {
112 self.as_mut_ptr() as *mut T
115 }
116}
117
118pub struct Fifo<R, W = R> {
120 handle: RWHandle<zx::Fifo<R, W>>,
121}
122
123impl<R: FromBytes + IntoBytes, W: FromBytes + IntoBytes> AsRef<zx::Fifo<R, W>> for Fifo<R, W> {
124 fn as_ref(&self) -> &zx::Fifo<R, W> {
125 self.handle.get_ref()
126 }
127}
128
129impl<R: FromBytes + IntoBytes, W: FromBytes + IntoBytes> AsHandleRef for Fifo<R, W> {
130 fn as_handle_ref(&self) -> zx::HandleRef<'_> {
131 self.handle.get_ref().as_handle_ref()
132 }
133}
134
135impl<R: FromBytes + IntoBytes, W: FromBytes + IntoBytes> From<Fifo<R, W>> for zx::Fifo<R, W> {
136 fn from(fifo: Fifo<R, W>) -> zx::Fifo<R, W> {
137 fifo.handle.into_inner()
138 }
139}
140
141impl<R: FromBytes + IntoBytes, W: FromBytes + IntoBytes> Fifo<R, W> {
142 pub fn from_fifo(fifo: impl Into<zx::Fifo<R, W>>) -> Self {
148 Fifo { handle: RWHandle::new(fifo.into()) }
149 }
150
151 pub fn try_write<B: ?Sized + FifoWriteBuffer<W>>(
159 &self,
160 cx: &mut Context<'_>,
161 entries: &B,
162 ) -> Poll<Result<NonZeroUsize, zx::Status>> {
163 ready!(self.handle.poll_writable(cx)?);
164
165 let entries = entries.as_slice();
166 let fifo = self.as_ref();
167 loop {
170 let result = unsafe { fifo.write_raw(entries.as_ptr(), entries.len()) };
171 match result {
172 Err(zx::Status::SHOULD_WAIT) => ready!(self.handle.need_writable(cx)?),
173 Err(e) => return Poll::Ready(Err(e)),
174 Ok(count) => return Poll::Ready(Ok(count)),
175 }
176 }
177 }
178
179 pub fn try_read<B: ?Sized + FifoReadBuffer<R>>(
185 &self,
186 cx: &mut Context<'_>,
187 entries: &mut B,
188 ) -> Poll<Result<NonZeroUsize, zx::Status>> {
189 ready!(self.handle.poll_readable(cx)?);
190
191 let buf = entries.as_mut_ptr();
192 let count = entries.count();
193 let fifo = self.as_ref();
194
195 loop {
196 let result = unsafe { fifo.read_raw(buf, count) };
200
201 match result {
202 Err(zx::Status::SHOULD_WAIT) => ready!(self.handle.need_readable(cx)?),
203 Err(e) => return Poll::Ready(Err(e)),
204 Ok(count) => return Poll::Ready(Ok(count)),
205 }
206 }
207 }
208
209 pub fn async_io(&mut self) -> (FifoReader<'_, R, W>, FifoWriter<'_, R, W>) {
212 (FifoReader(self), FifoWriter(self))
213 }
214}
215
216pub struct FifoWriter<'a, R, W>(&'a Fifo<R, W>);
217
218impl<R: FifoEntry, W: FifoEntry> FifoWriter<'_, R, W> {
219 pub async fn write_entries(
222 &mut self,
223 entries: &(impl ?Sized + FifoWriteBuffer<W>),
224 ) -> Result<(), zx::Status> {
225 let mut entries = entries.as_slice();
226 poll_fn(|cx| {
227 while !entries.is_empty() {
228 match ready!(self.0.try_write(cx, entries)) {
229 Ok(count) => entries = &entries[count.get()..],
230 Err(status) => return Poll::Ready(Err(status)),
231 }
232 }
233 Poll::Ready(Ok(()))
234 })
235 .await
236 }
237
238 pub fn try_write<B: ?Sized + FifoWriteBuffer<W>>(
240 &mut self,
241 cx: &mut Context<'_>,
242 entries: &B,
243 ) -> Poll<Result<NonZeroUsize, zx::Status>> {
244 self.0.try_write(cx, entries)
245 }
246}
247
248pub struct FifoReader<'a, R, W>(&'a Fifo<R, W>);
249
250impl<R: FifoEntry, W: FifoEntry> FifoReader<'_, R, W> {
251 pub async fn read_entries(
252 &mut self,
253 entries: &mut (impl ?Sized + FifoReadBuffer<R>),
254 ) -> Result<NonZeroUsize, zx::Status> {
255 poll_fn(|cx| self.0.try_read(cx, entries)).await
256 }
257
258 pub fn try_read<B: ?Sized + FifoReadBuffer<R>>(
260 &mut self,
261 cx: &mut Context<'_>,
262 entries: &mut B,
263 ) -> Poll<Result<NonZeroUsize, zx::Status>> {
264 self.0.try_read(cx, entries)
265 }
266}
267
268impl<R: FromBytes + IntoBytes, W: FromBytes + IntoBytes> fmt::Debug for Fifo<R, W> {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 self.handle.get_ref().fmt(f)
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277 use crate::{DurationExt, TestExecutor, Timer};
278 use futures::future::try_join;
279 use futures::prelude::*;
280 use zerocopy::{Immutable, KnownLayout};
281
282 #[derive(
283 Copy, Clone, Debug, PartialEq, Eq, Default, IntoBytes, KnownLayout, FromBytes, Immutable,
284 )]
285 #[repr(C)]
286 struct Entry {
287 a: u32,
288 b: u32,
289 }
290
291 #[derive(
292 Clone, Debug, PartialEq, Eq, Default, IntoBytes, KnownLayout, FromBytes, Immutable,
293 )]
294 #[repr(C)]
295 struct WrongEntry {
296 a: u16,
297 }
298
299 #[test]
300 fn can_read_write() {
301 let mut exec = TestExecutor::new();
302 let element = Entry { a: 10, b: 20 };
303
304 let (tx, rx) = zx::Fifo::<Entry>::create(2).expect("failed to create zx fifo");
305 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
306 let (_, mut tx) = tx.async_io();
307 let (mut rx, _) = rx.async_io();
308
309 let mut buffer = Entry::default();
310 let receiver = rx.read_entries(&mut buffer).map_ok(|count| {
311 assert_eq!(count.get(), 1);
312 });
313
314 let sender = Timer::new(zx::MonotonicDuration::from_millis(10).after_now())
316 .then(|()| tx.write_entries(&element));
317
318 let done = try_join(receiver, sender);
319 exec.run_singlethreaded(done).expect("failed to run receive future on executor");
320 assert_eq!(buffer, element);
321 }
322
323 #[test]
324 fn read_wrong_size() {
325 let mut exec = TestExecutor::new();
326 let elements = &[Entry { a: 10, b: 20 }][..];
327
328 let (tx, rx) = zx::Fifo::<Entry>::create(2).expect("failed to create zx fifo");
329 let wrong_rx = zx::Fifo::<WrongEntry>::from(rx.into_handle());
330 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(wrong_rx));
331 let (_, mut tx) = tx.async_io();
332 let (mut rx, _) = rx.async_io();
333
334 let mut buffer = WrongEntry::default();
335 let receiver = rx
336 .read_entries(&mut buffer)
337 .map_ok(|count| panic!("read should have failed, got {count}"));
338
339 let sender = Timer::new(zx::MonotonicDuration::from_millis(10).after_now())
341 .then(|()| tx.write_entries(elements));
342
343 let done = try_join(receiver, sender);
344 let res = exec.run_singlethreaded(done);
345 match res {
346 Err(zx::Status::OUT_OF_RANGE) => (),
347 _ => panic!("did not get out-of-range error"),
348 }
349 }
350
351 #[test]
352 fn write_wrong_size() {
353 let mut exec = TestExecutor::new();
354 let elements = &[WrongEntry { a: 10 }][..];
355
356 let (tx, rx) = zx::Fifo::<Entry>::create(2).expect("failed to create zx fifo");
357 let wrong_tx = zx::Fifo::<WrongEntry>::from(tx.into_handle());
358 let wrong_rx = zx::Fifo::<WrongEntry>::from(rx.into_handle());
359 let (mut tx, _rx) = (Fifo::from_fifo(wrong_tx), Fifo::from_fifo(wrong_rx));
360 let (_, mut tx) = tx.async_io();
361
362 let sender = Timer::new(zx::MonotonicDuration::from_millis(10).after_now())
363 .then(|()| tx.write_entries(elements));
364
365 let res = exec.run_singlethreaded(sender);
366 match res {
367 Err(zx::Status::OUT_OF_RANGE) => (),
368 _ => panic!("did not get out-of-range error"),
369 }
370 }
371
372 #[test]
373 fn write_into_full() {
374 use std::sync::atomic::{AtomicUsize, Ordering};
375
376 let mut exec = TestExecutor::new();
377 let elements =
378 &[Entry { a: 10, b: 20 }, Entry { a: 30, b: 40 }, Entry { a: 50, b: 60 }][..];
379
380 let (tx, rx) = zx::Fifo::<Entry>::create(2).expect("failed to create zx fifo");
381 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
382
383 let writes_completed = AtomicUsize::new(0);
386 let sender = async {
387 let (_, mut writer) = tx.async_io();
388 writer.write_entries(&elements[..2]).await?;
389 writes_completed.fetch_add(1, Ordering::SeqCst);
390 writer.write_entries(&elements[2..]).await?;
391 writes_completed.fetch_add(1, Ordering::SeqCst);
392 Ok::<(), zx::Status>(())
393 };
394
395 let receiver = async {
397 Timer::new(zx::MonotonicDuration::from_millis(10).after_now()).await;
398 let mut buffer = Entry::default();
399 let (mut reader, _) = rx.async_io();
400 let count = reader.read_entries(&mut buffer).await?;
401 assert_eq!(writes_completed.load(Ordering::SeqCst), 1);
402 assert_eq!(count.get(), 1);
403 assert_eq!(buffer, elements[0]);
404 let count = reader.read_entries(&mut buffer).await?;
405 assert_eq!(count.get(), 1);
408 assert_eq!(buffer, elements[1]);
409 let count = reader.read_entries(&mut buffer).await?;
410 assert_eq!(writes_completed.load(Ordering::SeqCst), 2);
411 assert_eq!(count.get(), 1);
412 assert_eq!(buffer, elements[2]);
413 Ok::<(), zx::Status>(())
414 };
415
416 let done = try_join(receiver, sender);
417
418 exec.run_singlethreaded(done).expect("failed to run receive future on executor");
419 }
420
421 #[test]
422 fn write_more_than_full() {
423 let mut exec = TestExecutor::new();
424 let elements =
425 &[Entry { a: 10, b: 20 }, Entry { a: 30, b: 40 }, Entry { a: 50, b: 60 }][..];
426
427 let (tx, rx) = zx::Fifo::<Entry>::create(2).expect("failed to create zx fifo");
428 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
429 let (_, mut tx) = tx.async_io();
430 let (mut rx, _) = rx.async_io();
431
432 let sender = tx.write_entries(elements);
433
434 let receiver = async {
436 Timer::new(zx::MonotonicDuration::from_millis(10).after_now()).await;
437 for e in elements {
438 let mut buffer = [Entry::default(); 1];
439 let count = rx.read_entries(&mut buffer[..]).await?;
440 assert_eq!(count.get(), 1);
441 assert_eq!(&buffer[0], e);
442 }
443 Ok::<(), zx::Status>(())
444 };
445
446 let done = try_join(receiver, sender);
447
448 exec.run_singlethreaded(done).expect("failed to run receive future on executor");
449 }
450
451 #[test]
452 fn read_multiple() {
453 let mut exec = TestExecutor::new();
454 let elements =
455 &[Entry { a: 10, b: 20 }, Entry { a: 30, b: 40 }, Entry { a: 50, b: 60 }][..];
456 let (tx, rx) = zx::Fifo::<Entry>::create(elements.len()).expect("failed to create zx fifo");
457 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
458
459 let write_fut = async {
460 tx.async_io().1.write_entries(elements).await.expect("failed write entries");
461 };
462 let read_fut = async {
463 let mut buffer = [Entry::default(); 5];
465 let count = rx
466 .async_io()
467 .0
468 .read_entries(&mut buffer[..])
469 .await
470 .expect("failed to read entries");
471 assert_eq!(count.get(), elements.len());
472 assert_eq!(&buffer[..count.get()], elements);
473 };
474 let ((), ()) = exec.run_singlethreaded(futures::future::join(write_fut, read_fut));
475 }
476
477 #[test]
478 fn read_one() {
479 let mut exec = TestExecutor::new();
480 let elements =
481 &[Entry { a: 10, b: 20 }, Entry { a: 30, b: 40 }, Entry { a: 50, b: 60 }][..];
482 let (tx, rx) = zx::Fifo::<Entry>::create(elements.len()).expect("failed to create zx fifo");
483 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
484
485 let write_fut = async {
486 tx.async_io().1.write_entries(elements).await.expect("failed write entries");
487 };
488 let read_fut = async {
489 let (mut reader, _) = rx.async_io();
490 for e in elements {
491 let mut entry = Entry::default();
492 assert_eq!(
493 reader.read_entries(&mut entry).await.expect("failed to read entry").get(),
494 1
495 );
496 assert_eq!(&entry, e);
497 }
498 };
499 let ((), ()) = exec.run_singlethreaded(futures::future::join(write_fut, read_fut));
500 }
501
502 #[test]
503 fn maybe_uninit_single() {
504 let mut exec = TestExecutor::new();
505 let element = Entry { a: 10, b: 20 };
506 let (tx, rx) = zx::Fifo::<Entry>::create(1).expect("failed to create zx fifo");
507 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
508
509 let write_fut = async {
510 tx.async_io().1.write_entries(&element).await.expect("failed write entries");
511 };
512 let read_fut = async {
513 let mut buffer = MaybeUninit::<Entry>::uninit();
514 let count =
515 rx.async_io().0.read_entries(&mut buffer).await.expect("failed to read entries");
516 assert_eq!(count.get(), 1);
517 let read = unsafe { buffer.assume_init() };
519 assert_eq!(read, element);
520 };
521 let ((), ()) = exec.run_singlethreaded(futures::future::join(write_fut, read_fut));
522 }
523
524 #[test]
525 fn maybe_uninit_slice() {
526 let mut exec = TestExecutor::new();
527 let elements =
528 &[Entry { a: 10, b: 20 }, Entry { a: 30, b: 40 }, Entry { a: 50, b: 60 }][..];
529 let (tx, rx) = zx::Fifo::<Entry>::create(elements.len()).expect("failed to create zx fifo");
530 let (mut tx, mut rx) = (Fifo::from_fifo(tx), Fifo::from_fifo(rx));
531
532 let write_fut = async {
533 tx.async_io().1.write_entries(elements).await.expect("failed write entries");
534 };
535 let read_fut = async {
536 let mut buffer = [MaybeUninit::<Entry>::uninit(); 15];
538 let count = rx
539 .async_io()
540 .0
541 .read_entries(&mut buffer[..])
542 .await
543 .expect("failed to read entries");
544 assert_eq!(count.get(), elements.len());
545 let read = &mut buffer[..count.get()];
546 for (i, v) in read.iter_mut().enumerate() {
547 let read = unsafe { v.assume_init_ref() };
550 assert_eq!(read, &elements[i]);
551 unsafe {
555 v.assume_init_drop();
556 }
557 }
558 };
559 let ((), ()) = exec.run_singlethreaded(futures::future::join(write_fut, read_fut));
560 }
561}