Revision control

Copy as Markdown

Other Tools

// 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
// 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!();
}