blob: d6be692db0b7e64822abc5439acad1b621087ccf [file] [log] [blame]
// Copyright 2025 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.
use crate::sys::zx_iovec_t;
use std::ops::Deref;
/// A reference to a readable slice of memory for IOB writes, analogous to `std::io::IoSlice` but
/// for Zircon IOB I/O. ABI-compatible with `zx_iovec_t`, guaranteeing the pointed-to bytes are
/// readable using lifetimes.
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IobIoSlice<'a>(zx_iovec_t, std::marker::PhantomData<&'a [u8]>);
impl<'a> IobIoSlice<'a> {
/// Convert a Rust byte slice to a `IobIoSlice`. If the input slice is longer than can be
/// referenced by a `zx_iovec_t` the length will be truncated.
pub fn new(buf: &'a [u8]) -> Self {
Self(zx_iovec_t { buffer: buf.as_ptr(), capacity: buf.len() }, std::marker::PhantomData)
}
}
impl<'a> Deref for IobIoSlice<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
// SAFETY: lifetime marker guarantees these bytes are still live.
unsafe { std::slice::from_raw_parts(self.0.buffer, self.0.capacity as usize) }
}
}
impl<'a> std::cmp::PartialEq for IobIoSlice<'a> {
fn eq(&self, rhs: &Self) -> bool {
self.deref().eq(rhs.deref())
}
}
impl<'a> std::cmp::Eq for IobIoSlice<'a> {}
impl<'a> std::hash::Hash for IobIoSlice<'a> {
fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
self.deref().hash(h)
}
}
impl<'a> std::fmt::Debug for IobIoSlice<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.deref().fmt(f)
}
}
// SAFETY: this type has no meaningful drop impl other than releasing its borrow.
unsafe impl<'a> Send for IobIoSlice<'a> {}
// SAFETY: this type has no mutability.
unsafe impl<'a> Sync for IobIoSlice<'a> {}