blob: 5543214b700f327b3bae3c33cf551d82f08aff21 [file] [log] [blame]
// Copyright 2021 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.
#[allow(clippy::missing_safety_doc)] // TODO(fxbug.dev/99067)
/// Trait used to indicate that the implementing type can be efficiently
/// converted into a reference to the original OpenThread type identified by
/// `Self::OtType`.
///
/// Types which implement this trait may be opaque, but, unlike [`Boxable`], these
/// types are not necessarily opaque and not necessarily ownable. If a type is
/// not opaque then it will also implement the related trait [`Transparent`],
/// allowing it to be used by value.
///
/// ## SAFETY ##
///
/// This trait is unsafe because it is making an assertion about the
/// data's representation that must be verified by code review.
///
/// In order to safely implement this trait you must verify that the implementing
/// type is guaranteed to always be fundamentally identical in its in-memory
/// representation to `<Self as OtCastable>::OtType`.
///
/// For example, this would be the case if `Self` is `#[repr(transparent)]` and
/// has only a single member of `<Self as OtCastable>::OtType`.
pub unsafe trait OtCastable: Sized {
/// Original OpenThread Type.
type OtType: Sized;
/// Returns a reference to the original OpenThread type [`Self::OtType`].
fn as_ot_ref(&self) -> &Self::OtType {
unsafe { &*self.as_ot_ptr() }
}
/// Returns a mutable reference to the original OpenThread type [`Self::OtType`].
fn as_ot_mut(&mut self) -> &mut Self::OtType {
unsafe { &mut *self.as_ot_mut_ptr() }
}
/// Returns a pointer to the underlying [`Self::OtType`] instance.
fn as_ot_ptr(&self) -> *const Self::OtType;
/// Returns a mutable pointer to the underlying [`Self::OtType`] instance.
fn as_ot_mut_ptr(&mut self) -> *mut Self::OtType;
/// Creates a reference from a pointer to an [`Self::OtType`].
///
/// ## Safety ##
///
/// This method is unsafe because unchecked conversion of pointers
/// to references is generally unsafe. The following assumptions
/// need to be verified to avoid undefined behavior:
///
/// 1. `ptr` MUST NOT be `NULL`.
/// 2. `ptr` MUST point to a valid instance of [`Self::OtType`].
unsafe fn ref_from_ot_ptr<'a>(ptr: *const Self::OtType) -> Option<&'a Self>;
/// Creates a mut reference from a mut pointer to an [`Self::OtType`].
///
/// ## Safety ##
///
/// This method is unsafe because unchecked conversion of pointers
/// to references is generally unsafe. The following assumptions
/// need to be verified to avoid undefined behavior:
///
/// 1. `ptr` MUST NOT be `NULL`.
/// 2. `ptr` MUST point to a valid instance of [`Self::OtType`].
unsafe fn mut_from_ot_mut_ptr<'a>(ptr: *mut Self::OtType) -> Option<&'a mut Self>;
/// Casts a reference to the original OpenThread type to a reference to `Self`.
fn ref_from_ot_ref(x: &Self::OtType) -> &Self {
unsafe { Self::ref_from_ot_ptr(x as *const Self::OtType) }.unwrap()
}
}
/// Trait used to indicate that the implementing type can be used by value
/// and converted to/from the associated OpenThread type by value.
///
/// Unlike types that implement the trait [`Boxable`], types implementing
/// this trait may be passed and used by value.
pub trait Transparent: OtCastable + Clone {
/// Creates a new instance from an instance of [`Self::OtType`].
fn from_ot(x: Self::OtType) -> Self;
/// Converts this type into an instance of [`Self::OtType`].
fn into_ot(self) -> Self::OtType;
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_ot_castable {
(opaque from_only $wrapper:ty,$inner:ty) => {
impl<'a> From<&'a $inner> for &'a $wrapper {
fn from(x: &'a $inner) -> Self {
<$wrapper>::ref_from_ot_ref(x)
}
}
impl<'a> From<&'a $wrapper> for &'a $inner {
fn from(x: &'a $wrapper) -> Self {
x.as_ot_ref()
}
}
};
(from_only $wrapper:ty,$inner:ty) => {
impl_ot_castable!(opaque from_only $wrapper, $inner);
impl From<$inner> for $wrapper {
fn from(x: $inner) -> Self {
Self(x)
}
}
impl From<$wrapper> for $inner {
fn from(x: $wrapper) -> Self {
x.0
}
}
};
($wrapper:ty,$inner:ty) => {
impl_ot_castable!(lifetime $wrapper, $inner);
impl_ot_castable!(from_only $wrapper, $inner);
};
(opaque $wrapper:ty,$inner:ty) => {
impl_ot_castable!(opaque lifetime $wrapper, $inner);
impl_ot_castable!(opaque from_only $wrapper, $inner);
};
(lifetime $wrapper:ty,$inner:ty) => {
impl_ot_castable!(lifetime $wrapper, $inner,);
};
(opaque lifetime $wrapper:ty,$inner:ty) => {
impl_ot_castable!(opaque lifetime $wrapper, $inner,);
};
(opaque lifetime $wrapper:ty,$inner:ty, $($other:expr),*) => {
// Note that we don't implement the PointerSafe trait on
// types with lifetimes.
unsafe impl $crate::ot::OtCastable for $wrapper {
type OtType = $inner;
fn as_ot_ptr(&self) -> *const Self::OtType {
&self.0 as *const Self::OtType
}
fn as_ot_mut_ptr(&mut self) -> *mut Self::OtType {
&mut self.0 as *mut Self::OtType
}
unsafe fn ref_from_ot_ptr<'a>(ptr: *const Self::OtType) -> Option<&'a Self> {
static_assertions::assert_eq_size!($wrapper, $inner);
static_assertions::assert_eq_align!($wrapper, $inner);
if ptr.is_null() {
None
} else {
Some(&*(ptr as *const Self))
}
}
unsafe fn mut_from_ot_mut_ptr<'a>(ptr: *mut Self::OtType) -> Option<&'a mut Self> {
static_assertions::assert_eq_size!($wrapper, $inner);
static_assertions::assert_eq_align!($wrapper, $inner);
if ptr.is_null() {
None
} else {
Some(&mut *(ptr as *mut Self))
}
}
}
};
(lifetime $wrapper:ty,$inner:ty, $($other:expr),*) => {
impl_ot_castable!(opaque lifetime $wrapper, $inner, $($other),*);
// Note that we don't implement the PointerSafe trait on
// types with lifetimes.
impl $crate::ot::Transparent for $wrapper {
fn from_ot(x: Self::OtType) -> Self {
Self(x,$($other),*)
}
fn into_ot(self) -> Self::OtType {
self.0
}
}
};
}