zx/iob/
io_slice.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::sys::zx_iovec_t;
6use std::ops::Deref;
7
8/// A reference to a readable slice of memory for IOB writes, analogous to `std::io::IoSlice` but
9/// for Zircon IOB I/O. ABI-compatible with `zx_iovec_t`, guaranteeing the pointed-to bytes are
10/// readable using lifetimes.
11#[derive(Copy, Clone)]
12#[repr(transparent)]
13pub struct IobIoSlice<'a>(zx_iovec_t, std::marker::PhantomData<&'a [u8]>);
14
15impl<'a> IobIoSlice<'a> {
16    /// Convert a Rust byte slice to a `IobIoSlice`. If the input slice is longer than can be
17    /// referenced by a `zx_iovec_t` the length will be truncated.
18    pub fn new(buf: &'a [u8]) -> Self {
19        Self(zx_iovec_t { buffer: buf.as_ptr(), capacity: buf.len() }, std::marker::PhantomData)
20    }
21}
22
23impl<'a> Deref for IobIoSlice<'a> {
24    type Target = [u8];
25    fn deref(&self) -> &[u8] {
26        // SAFETY: lifetime marker guarantees these bytes are still live.
27        unsafe { std::slice::from_raw_parts(self.0.buffer, self.0.capacity as usize) }
28    }
29}
30
31impl<'a> std::cmp::PartialEq for IobIoSlice<'a> {
32    fn eq(&self, rhs: &Self) -> bool {
33        self.deref().eq(rhs.deref())
34    }
35}
36impl<'a> std::cmp::Eq for IobIoSlice<'a> {}
37
38impl<'a> std::hash::Hash for IobIoSlice<'a> {
39    fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
40        self.deref().hash(h)
41    }
42}
43
44impl<'a> std::fmt::Debug for IobIoSlice<'a> {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        self.deref().fmt(f)
47    }
48}
49
50// SAFETY: this type has no meaningful drop impl other than releasing its borrow.
51unsafe impl<'a> Send for IobIoSlice<'a> {}
52
53// SAFETY: this type has no mutability.
54unsafe impl<'a> Sync for IobIoSlice<'a> {}