yoke/
macro_impls.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5// In this case consistency between impls is more important
6// than using pointer casts
7#![allow(clippy::transmute_ptr_to_ptr)]
8
9use crate::Yokeable;
10use core::{mem, ptr};
11
12macro_rules! copy_yoke_impl {
13    () => {
14        #[inline]
15        fn transform(&self) -> &Self::Output {
16            self
17        }
18        #[inline]
19        fn transform_owned(self) -> Self::Output {
20            self
21        }
22        #[inline]
23        unsafe fn make(this: Self::Output) -> Self {
24            this
25        }
26        #[inline]
27        fn transform_mut<F>(&'a mut self, f: F)
28        where
29            F: 'static + for<'b> FnOnce(&'b mut Self::Output),
30        {
31            f(self)
32        }
33    };
34}
35macro_rules! impl_copy_type {
36    ($ty:ident) => {
37        unsafe impl<'a> Yokeable<'a> for $ty {
38            type Output = Self;
39            copy_yoke_impl!();
40        }
41    };
42}
43
44impl_copy_type!(u8);
45impl_copy_type!(u16);
46impl_copy_type!(u32);
47impl_copy_type!(u64);
48impl_copy_type!(u128);
49impl_copy_type!(usize);
50impl_copy_type!(i8);
51impl_copy_type!(i16);
52impl_copy_type!(i32);
53impl_copy_type!(i64);
54impl_copy_type!(i128);
55impl_copy_type!(isize);
56impl_copy_type!(char);
57impl_copy_type!(bool);
58
59// This is for when we're implementing Yoke on a complex type such that it's not
60// obvious to the compiler that the lifetime is covariant
61macro_rules! unsafe_complex_yoke_impl {
62    () => {
63        fn transform(&'a self) -> &'a Self::Output {
64            unsafe { mem::transmute(self) }
65        }
66
67        fn transform_owned(self) -> Self::Output {
68            debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
69            unsafe {
70                let ptr: *const Self::Output = (&self as *const Self).cast();
71                mem::forget(self);
72                ptr::read(ptr)
73            }
74        }
75
76        unsafe fn make(from: Self::Output) -> Self {
77            debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
78            let ptr: *const Self = (&from as *const Self::Output).cast();
79            mem::forget(from);
80            ptr::read(ptr)
81        }
82
83        fn transform_mut<F>(&'a mut self, f: F)
84        where
85            F: 'static + for<'b> FnOnce(&'b mut Self::Output),
86        {
87            // Cast away the lifetime of Self
88            unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
89        }
90    };
91}
92
93unsafe impl<'a, T: 'static + for<'b> Yokeable<'b>> Yokeable<'a> for Option<T> {
94    type Output = Option<<T as Yokeable<'a>>::Output>;
95    unsafe_complex_yoke_impl!();
96}
97
98unsafe impl<'a, T1: 'static + for<'b> Yokeable<'b>, T2: 'static + for<'b> Yokeable<'b>> Yokeable<'a>
99    for (T1, T2)
100{
101    type Output = (<T1 as Yokeable<'a>>::Output, <T2 as Yokeable<'a>>::Output);
102    unsafe_complex_yoke_impl!();
103}
104
105unsafe impl<'a, T: Yokeable<'a>, const N: usize> Yokeable<'a> for [T; N] {
106    type Output = [<T as Yokeable<'a>>::Output; N];
107    unsafe_complex_yoke_impl!();
108}