astd/convert.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
//! The [`convert`] module provides operations and trait utilities for
//! conversions.
//!
//! [`convert`]: crate::convert
use std::convert::Infallible;
/// Simple and safe ownership acquisition of sub-elements of a type.
///
/// Any caller of this trait that acquires the underlying element must abide by
/// the underlying requirements of that type for resource destruction.
pub trait Take<T>
where
T: Sized,
{
/// Takes ownership of the underlying `T` element that is a sub-resource of
/// this type.
///
/// # Safety
///
/// The caller of this function must ensure that they take responsibility of
/// the underlying `T` element if ownership is safely acquired. This may
/// require manually dropping or destroying the underlying resource in a safe
/// way.
unsafe fn take(self) -> T;
}
/// Simple and safe ownership acquisition of sub-elements of a type.
///
/// This generalizes the [`Take`] trait to enable failure conditions for the
/// case of any acquisition failures.
///
/// Any caller of this trait that successfully acquires the underlying element
/// must abide by the underlying requirements of that type for resource
/// destruction.
pub trait TryTake<T>
where
T: Sized,
{
/// The possible error type that might occur when trying to take ownership
/// of the underlying `T`.
type Error;
/// Attempts to take ownership of the underlying `T` element from this object.
///
/// # Safety
///
/// The caller of this function must ensure that they take responsibility of
/// the underlying `T` element if ownership is safely acquired. This may
/// require manually dropping or destroying the underlying resource in a safe
/// way.
unsafe fn try_take(self) -> Result<T, Self::Error>;
}
impl<T, U> TryTake<T> for U
where
U: Take<T>,
{
type Error = Infallible;
unsafe fn try_take(self) -> Result<T, Self::Error> {
Ok(self.take())
}
}
/// Transparent is a trait that indicates that the implementor is a transparent
/// wrapper around some type, and should be treated interoperably with wrapped
/// type.
///
/// This allows for internal types to be treated as references of the wrapper
/// type, and vice-versa.
///
/// # Note
///
/// This trait only allows for conversions between _references_ of objects;
/// this means that the formed references will become ephemeral references of a
/// different type -- but the lifetime of the object will still be tied to the
/// lifetime of the source.
///
/// # Acknowledgements
///
/// The approach to use this trait is heavily inspired by the [`bytemuck`] crate,
/// which is licensed under ZLib OR MIT OR Apache-2. The idea has been adapted
/// for this library's specific needs.
///
/// # Safety
///
/// The safety contract for this type requires two things:
///
/// * The wrapper type implementing this must be `#[repr(transparent)]`
/// * The implementation must not override the function definitions in the trait.
///
/// [`bytemuck`]: https://crates.io/crates/bytemuck
pub unsafe trait Transparent {
/// The type that is wrapped by the Transparent impl.
type Wrapped: ?Sized;
/// Converts a reference to a type into a reference of the wrapper type.
///
/// # Safety
///
/// The safety contract for this type requires two things:
///
/// * The wrapper type implementing this must be `#[repr(transparent)]`
/// * This function must not be implemented in `impl`s.
#[inline]
fn from_ref(wrapped: &Self::Wrapped) -> &Self {
debug_assert!(
std::mem::size_of::<*const Self::Wrapped>() == std::mem::size_of::<*const Self>()
);
unsafe {
let ptr = wrapped as *const Self::Wrapped;
let wrapper: *const Self = std::mem::transmute_copy(&ptr);
&*wrapper
}
}
/// Converts a mut reference to a wrapped type into a mut reference to the
/// wrapper.
///
/// # Safety
///
/// The safety contract for this type requires two things:
///
/// * The wrapper type implementing this must be `#[repr(transparent)]`
/// * This function must not be implemented in `impl`s.
#[inline]
fn from_ref_mut(wrapped: &mut Self::Wrapped) -> &mut Self {
debug_assert!(std::mem::size_of::<*mut Self::Wrapped>() == std::mem::size_of::<*mut Self>());
unsafe {
let ptr = wrapped as *mut Self::Wrapped;
let wrapper: *mut Self = std::mem::transmute_copy(&ptr);
&mut *wrapper
}
}
}
/// Slices which are [`Transparent`] are convertible to their wrapped types.
unsafe impl<T> Transparent for [T]
where
T: Transparent,
T::Wrapped: Sized,
{
type Wrapped = [T::Wrapped];
}
/// Arrays which are [`Transparent`] are convertible to their wrapped types.
unsafe impl<const N: usize, T> Transparent for [T; N]
where
T: Transparent,
T::Wrapped: Sized,
{
type Wrapped = [T::Wrapped; N];
}
unsafe impl<T> Transparent for *const T
where
T: Transparent,
{
type Wrapped = *const T::Wrapped;
}
unsafe impl<T> Transparent for *mut T
where
T: Transparent,
{
type Wrapped = *mut T::Wrapped;
}
unsafe impl<T> Transparent for Vec<T>
where
T: Transparent,
T::Wrapped: Sized,
{
type Wrapped = Vec<T::Wrapped>;
}
unsafe impl<T> Transparent for Box<T>
where
T: Transparent,
{
type Wrapped = Box<T::Wrapped>;
}
unsafe impl<T> Transparent for std::sync::Arc<T>
where
T: Transparent,
{
type Wrapped = std::sync::Arc<T::Wrapped>;
}
unsafe impl<T> Transparent for std::rc::Rc<T>
where
T: Transparent,
{
type Wrapped = std::rc::Rc<T::Wrapped>;
}