diff options
Diffstat (limited to 'third_party/rust/yoke/src/macro_impls.rs')
-rw-r--r-- | third_party/rust/yoke/src/macro_impls.rs | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/third_party/rust/yoke/src/macro_impls.rs b/third_party/rust/yoke/src/macro_impls.rs new file mode 100644 index 0000000000..060061b209 --- /dev/null +++ b/third_party/rust/yoke/src/macro_impls.rs @@ -0,0 +1,108 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +// In this case consistency between impls is more important +// than using pointer casts +#![allow(clippy::transmute_ptr_to_ptr)] + +use crate::Yokeable; +use core::{mem, ptr}; + +macro_rules! copy_yoke_impl { + () => { + #[inline] + fn transform(&self) -> &Self::Output { + self + } + #[inline] + fn transform_owned(self) -> Self::Output { + self + } + #[inline] + unsafe fn make(this: Self::Output) -> Self { + this + } + #[inline] + fn transform_mut<F>(&'a mut self, f: F) + where + F: 'static + for<'b> FnOnce(&'b mut Self::Output), + { + f(self) + } + }; +} +macro_rules! impl_copy_type { + ($ty:ident) => { + unsafe impl<'a> Yokeable<'a> for $ty { + type Output = Self; + copy_yoke_impl!(); + } + }; +} + +impl_copy_type!(u8); +impl_copy_type!(u16); +impl_copy_type!(u32); +impl_copy_type!(u64); +impl_copy_type!(u128); +impl_copy_type!(usize); +impl_copy_type!(i8); +impl_copy_type!(i16); +impl_copy_type!(i32); +impl_copy_type!(i64); +impl_copy_type!(i128); +impl_copy_type!(isize); +impl_copy_type!(char); +impl_copy_type!(bool); + +// This is for when we're implementing Yoke on a complex type such that it's not +// obvious to the compiler that the lifetime is covariant +macro_rules! unsafe_complex_yoke_impl { + () => { + fn transform(&'a self) -> &'a Self::Output { + unsafe { mem::transmute(self) } + } + + fn transform_owned(self) -> Self::Output { + debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); + unsafe { + let ptr: *const Self::Output = (&self as *const Self).cast(); + mem::forget(self); + ptr::read(ptr) + } + } + + unsafe fn make(from: Self::Output) -> Self { + debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); + let ptr: *const Self = (&from as *const Self::Output).cast(); + mem::forget(from); + ptr::read(ptr) + } + + fn transform_mut<F>(&'a mut self, f: F) + where + F: 'static + for<'b> FnOnce(&'b mut Self::Output), + { + // Cast away the lifetime of Self + unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) } + } + }; +} + +unsafe impl<'a, T: 'static + for<'b> Yokeable<'b>> Yokeable<'a> for Option<T> { + type Output = Option<<T as Yokeable<'a>>::Output>; + unsafe_complex_yoke_impl!(); +} + +unsafe impl<'a, T1: 'static + for<'b> Yokeable<'b>, T2: 'static + for<'b> Yokeable<'b>> Yokeable<'a> + for (T1, T2) +{ + type Output = (<T1 as Yokeable<'a>>::Output, <T2 as Yokeable<'a>>::Output); + unsafe_complex_yoke_impl!(); +} + +unsafe impl<'a, T: Yokeable<'a>, const N: usize> Yokeable<'a> for [T; N] { + type Output = [<T as Yokeable<'a>>::Output; N]; + unsafe_complex_yoke_impl!(); +} |