zerovec/
yoke_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// This way we can copy-paste Yokeable impls
6#![allow(unknown_lints)] // forgetting_copy_types
7#![allow(renamed_and_removed_lints)] // forgetting_copy_types
8#![allow(forgetting_copy_types)]
9#![allow(clippy::forget_copy)]
10#![allow(clippy::forget_non_drop)]
11
12#[cfg(feature = "alloc")]
13use crate::map::ZeroMapBorrowed;
14#[cfg(feature = "alloc")]
15use crate::map::ZeroMapKV;
16#[cfg(feature = "alloc")]
17use crate::map2d::ZeroMap2dBorrowed;
18use crate::ule::*;
19use crate::{VarZeroCow, VarZeroVec, ZeroVec};
20#[cfg(feature = "alloc")]
21use crate::{ZeroMap, ZeroMap2d};
22use core::{mem, ptr};
23use yoke::*;
24
25// This impl is similar to the impl on Cow and is safe for the same reasons
26/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
27unsafe impl<'a, T: 'static + AsULE> Yokeable<'a> for ZeroVec<'static, T> {
28    type Output = ZeroVec<'a, T>;
29    #[inline]
30    fn transform(&'a self) -> &'a Self::Output {
31        self
32    }
33    #[inline]
34    fn transform_owned(self) -> Self::Output {
35        self
36    }
37    #[inline]
38    unsafe fn make(from: Self::Output) -> Self {
39        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
40        let from = mem::ManuallyDrop::new(from);
41        let ptr: *const Self = (&*from as *const Self::Output).cast();
42        ptr::read(ptr)
43    }
44    #[inline]
45    fn transform_mut<F>(&'a mut self, f: F)
46    where
47        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
48    {
49        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
50    }
51}
52
53// This impl is similar to the impl on Cow and is safe for the same reasons
54/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
55unsafe impl<'a, T: 'static + VarULE + ?Sized> Yokeable<'a> for VarZeroVec<'static, T> {
56    type Output = VarZeroVec<'a, T>;
57    #[inline]
58    fn transform(&'a self) -> &'a Self::Output {
59        self
60    }
61    #[inline]
62    fn transform_owned(self) -> Self::Output {
63        self
64    }
65    #[inline]
66    unsafe fn make(from: Self::Output) -> Self {
67        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
68        let from = mem::ManuallyDrop::new(from);
69        let ptr: *const Self = (&*from as *const Self::Output).cast();
70        ptr::read(ptr)
71    }
72    #[inline]
73    fn transform_mut<F>(&'a mut self, f: F)
74    where
75        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
76    {
77        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
78    }
79}
80
81// This impl is similar to the impl on Cow and is safe for the same reasons
82/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
83unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for VarZeroCow<'static, T> {
84    type Output = VarZeroCow<'a, T>;
85    #[inline]
86    fn transform(&'a self) -> &'a Self::Output {
87        self
88    }
89    #[inline]
90    fn transform_owned(self) -> Self::Output {
91        self
92    }
93    #[inline]
94    unsafe fn make(from: Self::Output) -> Self {
95        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
96        let from = mem::ManuallyDrop::new(from);
97        let ptr: *const Self = (&*from as *const Self::Output).cast();
98        ptr::read(ptr)
99    }
100    #[inline]
101    fn transform_mut<F>(&'a mut self, f: F)
102    where
103        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
104    {
105        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
106    }
107}
108
109/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
110#[cfg(feature = "alloc")]
111unsafe impl<'a, K, V> Yokeable<'a> for ZeroMap<'static, K, V>
112where
113    K: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
114    V: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
115    <K as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>,
116    <V as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>,
117{
118    type Output = ZeroMap<'a, K, V>;
119    #[inline]
120    fn transform(&'a self) -> &'a Self::Output {
121        unsafe {
122            // Unfortunately, because K and V are generic, rustc is
123            // unaware that these are covariant types, and cannot perform this cast automatically.
124            // We transmute it instead, and enforce the lack of a lifetime with the `K, V: 'static` bound
125            mem::transmute::<&Self, &Self::Output>(self)
126        }
127    }
128    #[inline]
129    fn transform_owned(self) -> Self::Output {
130        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
131        unsafe {
132            // Similar problem as transform(), but we need to use ptr::read since
133            // the compiler isn't sure of the sizes
134            let this = mem::ManuallyDrop::new(self);
135            let ptr: *const Self::Output = (&*this as *const Self).cast();
136            ptr::read(ptr)
137        }
138    }
139    #[inline]
140    unsafe fn make(from: Self::Output) -> Self {
141        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
142        let from = mem::ManuallyDrop::new(from);
143        let ptr: *const Self = (&*from as *const Self::Output).cast();
144        ptr::read(ptr)
145    }
146    #[inline]
147    fn transform_mut<F>(&'a mut self, f: F)
148    where
149        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
150    {
151        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
152    }
153}
154
155/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
156#[cfg(feature = "alloc")]
157unsafe impl<'a, K, V> Yokeable<'a> for ZeroMapBorrowed<'static, K, V>
158where
159    K: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
160    V: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
161    &'static <K as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>,
162    &'static <V as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>,
163{
164    type Output = ZeroMapBorrowed<'a, K, V>;
165    #[inline]
166    fn transform(&'a self) -> &'a Self::Output {
167        unsafe {
168            // Unfortunately, because K and V are generic, rustc is
169            // unaware that these are covariant types, and cannot perform this cast automatically.
170            // We transmute it instead, and enforce the lack of a lifetime with the `K, V: 'static` bound
171            mem::transmute::<&Self, &Self::Output>(self)
172        }
173    }
174    #[inline]
175    fn transform_owned(self) -> Self::Output {
176        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
177        unsafe {
178            // Similar problem as transform(), but we need to use ptr::read since
179            // the compiler isn't sure of the sizes
180            let this = mem::ManuallyDrop::new(self);
181            let ptr: *const Self::Output = (&*this as *const Self).cast();
182            ptr::read(ptr)
183        }
184    }
185    #[inline]
186    unsafe fn make(from: Self::Output) -> Self {
187        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
188        let from = mem::ManuallyDrop::new(from);
189        let ptr: *const Self = (&*from as *const Self::Output).cast();
190        ptr::read(ptr)
191    }
192    #[inline]
193    fn transform_mut<F>(&'a mut self, f: F)
194    where
195        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
196    {
197        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
198    }
199}
200
201/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
202#[cfg(feature = "alloc")]
203unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2d<'static, K0, K1, V>
204where
205    K0: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
206    K1: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
207    V: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
208    <K0 as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>,
209    <K1 as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>,
210    <V as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>,
211{
212    type Output = ZeroMap2d<'a, K0, K1, V>;
213    #[inline]
214    fn transform(&'a self) -> &'a Self::Output {
215        unsafe {
216            // Unfortunately, because K and V are generic, rustc is
217            // unaware that these are covariant types, and cannot perform this cast automatically.
218            // We transmute it instead, and enforce the lack of a lifetime with the `K0, K1, V: 'static` bound
219            mem::transmute::<&Self, &Self::Output>(self)
220        }
221    }
222    #[inline]
223    fn transform_owned(self) -> Self::Output {
224        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
225        unsafe {
226            // Similar problem as transform(), but we need to use ptr::read since
227            // the compiler isn't sure of the sizes
228            let this = mem::ManuallyDrop::new(self);
229            let ptr: *const Self::Output = (&*this as *const Self).cast();
230            ptr::read(ptr)
231        }
232    }
233    #[inline]
234    unsafe fn make(from: Self::Output) -> Self {
235        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
236        let from = mem::ManuallyDrop::new(from);
237        let ptr: *const Self = (&*from as *const Self::Output).cast();
238        ptr::read(ptr)
239    }
240    #[inline]
241    fn transform_mut<F>(&'a mut self, f: F)
242    where
243        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
244    {
245        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
246    }
247}
248
249/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
250#[cfg(feature = "alloc")]
251unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2dBorrowed<'static, K0, K1, V>
252where
253    K0: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
254    K1: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
255    V: 'static + for<'b> ZeroMapKV<'b> + ?Sized,
256    &'static <K0 as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>,
257    &'static <K1 as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>,
258    &'static <V as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>,
259{
260    type Output = ZeroMap2dBorrowed<'a, K0, K1, V>;
261    #[inline]
262    fn transform(&'a self) -> &'a Self::Output {
263        unsafe {
264            // Unfortunately, because K and V are generic, rustc is
265            // unaware that these are covariant types, and cannot perform this cast automatically.
266            // We transmute it instead, and enforce the lack of a lifetime with the `K0, K1, V: 'static` bound
267            mem::transmute::<&Self, &Self::Output>(self)
268        }
269    }
270    #[inline]
271    fn transform_owned(self) -> Self::Output {
272        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
273        unsafe {
274            // Similar problem as transform(), but we need to use ptr::read since
275            // the compiler isn't sure of the sizes
276            let this = mem::ManuallyDrop::new(self);
277            let ptr: *const Self::Output = (&*this as *const Self).cast();
278            ptr::read(ptr)
279        }
280    }
281    #[inline]
282    unsafe fn make(from: Self::Output) -> Self {
283        debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
284        let from = mem::ManuallyDrop::new(from);
285        let ptr: *const Self = (&*from as *const Self::Output).cast();
286        ptr::read(ptr)
287    }
288    #[inline]
289    fn transform_mut<F>(&'a mut self, f: F)
290    where
291        F: 'static + for<'b> FnOnce(&'b mut Self::Output),
292    {
293        unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
294    }
295}
296
297#[cfg(test)]
298#[allow(non_camel_case_types, non_snake_case)]
299mod test {
300    use super::*;
301    use crate::{VarZeroSlice, ZeroSlice};
302    use databake::*;
303
304    // Note: The following derives cover Yoke as well as Serde and databake. These may partially
305    // duplicate tests elsewhere in this crate, but they are here for completeness.
306
307    #[derive(yoke::Yokeable, zerofrom::ZeroFrom)]
308    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
309    #[cfg_attr(feature = "databake", derive(databake::Bake))]
310    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
311    struct DeriveTest_ZeroVec<'data> {
312        #[cfg_attr(feature = "serde", serde(borrow))]
313        pub _data: ZeroVec<'data, u16>,
314    }
315
316    #[test]
317    fn bake_ZeroVec() {
318        test_bake!(
319            DeriveTest_ZeroVec<'static>,
320            crate::yoke_impls::test::DeriveTest_ZeroVec {
321                _data: crate::ZeroVec::new(),
322            },
323            zerovec,
324        );
325    }
326
327    #[derive(yoke::Yokeable)]
328    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
329    #[cfg_attr(feature = "databake", derive(databake::Bake))]
330    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
331    struct DeriveTest_ZeroSlice<'data> {
332        #[cfg_attr(feature = "serde", serde(borrow))]
333        pub _data: &'data ZeroSlice<u16>,
334    }
335
336    #[test]
337    fn bake_ZeroSlice() {
338        test_bake!(
339            DeriveTest_ZeroSlice<'static>,
340            crate::yoke_impls::test::DeriveTest_ZeroSlice {
341                _data: crate::ZeroSlice::new_empty(),
342            },
343            zerovec,
344        );
345    }
346
347    #[derive(yoke::Yokeable, zerofrom::ZeroFrom)]
348    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
349    #[cfg_attr(feature = "databake", derive(databake::Bake))]
350    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
351    struct DeriveTest_VarZeroVec<'data> {
352        #[cfg_attr(feature = "serde", serde(borrow))]
353        pub _data: VarZeroVec<'data, str>,
354    }
355
356    #[test]
357    fn bake_VarZeroVec() {
358        test_bake!(
359            DeriveTest_VarZeroVec<'static>,
360            crate::yoke_impls::test::DeriveTest_VarZeroVec {
361                _data: crate::vecs::VarZeroVec16::new(),
362            },
363            zerovec,
364        );
365    }
366
367    #[derive(yoke::Yokeable)]
368    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
369    #[cfg_attr(feature = "databake", derive(databake::Bake))]
370    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
371    struct DeriveTest_VarZeroSlice<'data> {
372        #[cfg_attr(feature = "serde", serde(borrow))]
373        pub _data: &'data VarZeroSlice<str>,
374    }
375
376    #[test]
377    fn bake_VarZeroSlice() {
378        test_bake!(
379            DeriveTest_VarZeroSlice<'static>,
380            crate::yoke_impls::test::DeriveTest_VarZeroSlice {
381                _data: crate::vecs::VarZeroSlice16::new_empty()
382            },
383            zerovec,
384        );
385    }
386
387    #[derive(yoke::Yokeable, zerofrom::ZeroFrom)]
388    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
389    #[cfg_attr(feature = "databake", derive(databake::Bake))]
390    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
391    #[yoke(prove_covariance_manually)]
392    struct DeriveTest_ZeroMap<'data> {
393        #[cfg_attr(feature = "serde", serde(borrow))]
394        pub _data: ZeroMap<'data, [u8], str>,
395    }
396
397    #[test]
398    fn bake_ZeroMap() {
399        test_bake!(
400            DeriveTest_ZeroMap<'static>,
401            crate::yoke_impls::test::DeriveTest_ZeroMap {
402                _data: unsafe {
403                    #[allow(unused_unsafe)]
404                    crate::ZeroMap::from_parts_unchecked(
405                        crate::vecs::VarZeroVec16::new(),
406                        crate::vecs::VarZeroVec16::new(),
407                    )
408                },
409            },
410            zerovec,
411        );
412    }
413
414    #[derive(yoke::Yokeable)]
415    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
416    #[cfg_attr(feature = "databake", derive(databake::Bake))]
417    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
418    #[yoke(prove_covariance_manually)]
419    struct DeriveTest_ZeroMapBorrowed<'data> {
420        #[cfg_attr(feature = "serde", serde(borrow))]
421        pub _data: ZeroMapBorrowed<'data, [u8], str>,
422    }
423
424    #[test]
425    fn bake_ZeroMapBorrowed() {
426        test_bake!(
427            DeriveTest_ZeroMapBorrowed<'static>,
428            crate::yoke_impls::test::DeriveTest_ZeroMapBorrowed {
429                _data: unsafe {
430                    #[allow(unused_unsafe)]
431                    crate::maps::ZeroMapBorrowed::from_parts_unchecked(
432                        crate::vecs::VarZeroSlice16::new_empty(),
433                        crate::vecs::VarZeroSlice16::new_empty(),
434                    )
435                },
436            },
437            zerovec,
438        );
439    }
440
441    #[derive(yoke::Yokeable, zerofrom::ZeroFrom)]
442    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
443    #[cfg_attr(feature = "databake", derive(databake::Bake))]
444    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
445    #[yoke(prove_covariance_manually)]
446    struct DeriveTest_ZeroMapWithULE<'data> {
447        #[cfg_attr(feature = "serde", serde(borrow))]
448        pub _data: ZeroMap<'data, ZeroSlice<u32>, str>,
449    }
450
451    #[test]
452    fn bake_ZeroMapWithULE() {
453        test_bake!(
454            DeriveTest_ZeroMapWithULE<'static>,
455            crate::yoke_impls::test::DeriveTest_ZeroMapWithULE {
456                _data: unsafe {
457                    #[allow(unused_unsafe)]
458                    crate::ZeroMap::from_parts_unchecked(
459                        crate::vecs::VarZeroVec16::new(),
460                        crate::vecs::VarZeroVec16::new(),
461                    )
462                },
463            },
464            zerovec,
465        );
466    }
467
468    #[derive(yoke::Yokeable, zerofrom::ZeroFrom)]
469    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
470    #[cfg_attr(feature = "databake", derive(databake::Bake))]
471    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
472    #[yoke(prove_covariance_manually)]
473    struct DeriveTest_ZeroMap2d<'data> {
474        #[cfg_attr(feature = "serde", serde(borrow))]
475        pub _data: ZeroMap2d<'data, u16, u16, str>,
476    }
477
478    #[test]
479    fn bake_ZeroMap2d() {
480        test_bake!(
481            DeriveTest_ZeroMap2d<'static>,
482            crate::yoke_impls::test::DeriveTest_ZeroMap2d {
483                _data: unsafe {
484                    #[allow(unused_unsafe)]
485                    crate::ZeroMap2d::from_parts_unchecked(
486                        crate::ZeroVec::new(),
487                        crate::ZeroVec::new(),
488                        crate::ZeroVec::new(),
489                        crate::vecs::VarZeroVec16::new(),
490                    )
491                },
492            },
493            zerovec,
494        );
495    }
496
497    #[derive(yoke::Yokeable)]
498    #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
499    #[cfg_attr(feature = "databake", derive(databake::Bake))]
500    #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))]
501    #[yoke(prove_covariance_manually)]
502    struct DeriveTest_ZeroMap2dBorrowed<'data> {
503        #[cfg_attr(feature = "serde", serde(borrow))]
504        pub _data: ZeroMap2dBorrowed<'data, u16, u16, str>,
505    }
506
507    #[test]
508    fn bake_ZeroMap2dBorrowed() {
509        test_bake!(
510            DeriveTest_ZeroMap2dBorrowed<'static>,
511            crate::yoke_impls::test::DeriveTest_ZeroMap2dBorrowed {
512                _data: unsafe {
513                    #[allow(unused_unsafe)]
514                    crate::maps::ZeroMap2dBorrowed::from_parts_unchecked(
515                        crate::ZeroSlice::new_empty(),
516                        crate::ZeroSlice::new_empty(),
517                        crate::ZeroSlice::new_empty(),
518                        crate::vecs::VarZeroSlice16::new_empty(),
519                    )
520                },
521            },
522            zerovec,
523        );
524    }
525}