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 | |
9 | use crate::Yokeable; |
10 | use core::{mem, ptr}; |
11 | |
12 | macro_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 | } |
35 | macro_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 | |
44 | impl_copy_type!(u8); |
45 | impl_copy_type!(u16); |
46 | impl_copy_type!(u32); |
47 | impl_copy_type!(u64); |
48 | impl_copy_type!(u128); |
49 | impl_copy_type!(usize); |
50 | impl_copy_type!(i8); |
51 | impl_copy_type!(i16); |
52 | impl_copy_type!(i32); |
53 | impl_copy_type!(i64); |
54 | impl_copy_type!(i128); |
55 | impl_copy_type!(isize); |
56 | impl_copy_type!(char); |
57 | impl_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 |
61 | macro_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 | |
93 | unsafe 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 | |
98 | unsafe 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 | |
105 | unsafe 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 | } |
109 | |