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