summaryrefslogtreecommitdiffstats
path: root/third_party/rust/fuchsia-zircon/src/fifo.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/fuchsia-zircon/src/fifo.rs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/fuchsia-zircon/src/fifo.rs')
-rw-r--r--third_party/rust/fuchsia-zircon/src/fifo.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/third_party/rust/fuchsia-zircon/src/fifo.rs b/third_party/rust/fuchsia-zircon/src/fifo.rs
new file mode 100644
index 0000000000..20af6f5236
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/fifo.rs
@@ -0,0 +1,98 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon fifo objects.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef, Status};
+use {sys, ok};
+
+/// An object representing a Zircon fifo.
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Fifo(Handle);
+impl_handle_based!(Fifo);
+
+impl Fifo {
+ /// Create a pair of fifos and return their endpoints. Writing to one endpoint enqueues an
+ /// element into the fifo from which the opposing endpoint reads. Wraps the
+ /// [zx_fifo_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_create.md)
+ /// syscall.
+ pub fn create(elem_count: u32, elem_size: u32)
+ -> Result<(Fifo, Fifo), Status>
+ {
+ let mut out0 = 0;
+ let mut out1 = 0;
+ let options = 0;
+ let status = unsafe {
+ sys::zx_fifo_create(elem_count, elem_size, options, &mut out0, &mut out1)
+ };
+ ok(status)?;
+ unsafe { Ok((
+ Self::from(Handle::from_raw(out0)),
+ Self::from(Handle::from_raw(out1))
+ ))}
+ }
+
+ /// Attempts to write some number of elements into the fifo. The number of bytes written will be
+ /// rounded down to a multiple of the fifo's element size.
+ /// Return value (on success) is number of elements actually written.
+ ///
+ /// Wraps
+ /// [zx_fifo_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_write.md).
+ pub fn write(&self, bytes: &[u8]) -> Result<u32, Status> {
+ let mut num_entries_written = 0;
+ let status = unsafe {
+ sys::zx_fifo_write(self.raw_handle(), bytes.as_ptr(), bytes.len(),
+ &mut num_entries_written)
+ };
+ ok(status).map(|()| num_entries_written)
+ }
+
+ /// Attempts to read some number of elements out of the fifo. The number of bytes read will
+ /// always be a multiple of the fifo's element size.
+ /// Return value (on success) is number of elements actually read.
+ ///
+ /// Wraps
+ /// [zx_fifo_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_read.md).
+ pub fn read(&self, bytes: &mut [u8]) -> Result<u32, Status> {
+ let mut num_entries_read = 0;
+ let status = unsafe {
+ sys::zx_fifo_read(self.raw_handle(), bytes.as_mut_ptr(), bytes.len(),
+ &mut num_entries_read)
+ };
+ ok(status).map(|()| num_entries_read)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn fifo_basic() {
+ let (fifo1, fifo2) = Fifo::create(4, 2).unwrap();
+
+ // Trying to write less than one element should fail.
+ assert_eq!(fifo1.write(b""), Err(Status::OUT_OF_RANGE));
+ assert_eq!(fifo1.write(b"h"), Err(Status::OUT_OF_RANGE));
+
+ // Should write one element "he" and ignore the last half-element as it rounds down.
+ assert_eq!(fifo1.write(b"hex").unwrap(), 1);
+
+ // Should write three elements "ll" "o " "wo" and drop the rest as it is full.
+ assert_eq!(fifo1.write(b"llo worlds").unwrap(), 3);
+
+ // Now that the fifo is full any further attempts to write should fail.
+ assert_eq!(fifo1.write(b"blah blah"), Err(Status::SHOULD_WAIT));
+
+ // Read all 4 entries from the other end.
+ let mut read_vec = vec![0; 8];
+ assert_eq!(fifo2.read(&mut read_vec).unwrap(), 4);
+ assert_eq!(read_vec, b"hello wo");
+
+ // Reading again should fail as the fifo is empty.
+ assert_eq!(fifo2.read(&mut read_vec), Err(Status::SHOULD_WAIT));
+ }
+}