| // 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 |
| // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
| |
| // This way we can copy-paste Yokeable impls |
| #![allow(unknown_lints)] // forgetting_copy_types |
| #![allow(renamed_and_removed_lints)] // forgetting_copy_types |
| #![allow(forgetting_copy_types)] |
| #![allow(clippy::forget_copy)] |
| #![allow(clippy::forget_non_drop)] |
| |
| use crate::flexzerovec::FlexZeroVec; |
| use crate::map::ZeroMapBorrowed; |
| use crate::map::ZeroMapKV; |
| use crate::map2d::ZeroMap2dBorrowed; |
| use crate::ule::*; |
| use crate::{VarZeroVec, ZeroMap, ZeroMap2d, ZeroVec}; |
| use core::{mem, ptr}; |
| use yoke::*; |
| |
| // This impl is similar to the impl on Cow and is safe for the same reasons |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| unsafe impl<'a, T: 'static + AsULE + ?Sized> Yokeable<'a> for ZeroVec<'static, T> { |
| type Output = ZeroVec<'a, T>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| self |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| self |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| // This impl is similar to the impl on Cow and is safe for the same reasons |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| unsafe impl<'a, T: 'static + VarULE + ?Sized> Yokeable<'a> for VarZeroVec<'static, T> { |
| type Output = VarZeroVec<'a, T>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| self |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| self |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| // This impl is similar to the impl on Cow and is safe for the same reasons |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| unsafe impl<'a> Yokeable<'a> for FlexZeroVec<'static> { |
| type Output = FlexZeroVec<'a>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| self |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| self |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| #[allow(clippy::transmute_ptr_to_ptr)] |
| unsafe impl<'a, K, V> Yokeable<'a> for ZeroMap<'static, K, V> |
| where |
| K: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| <K as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>, |
| <V as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>, |
| { |
| type Output = ZeroMap<'a, K, V>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| unsafe { |
| // Unfortunately, because K and V are generic, rustc is |
| // unaware that these are covariant types, and cannot perform this cast automatically. |
| // We transmute it instead, and enforce the lack of a lifetime with the `K, V: 'static` bound |
| mem::transmute::<&Self, &Self::Output>(self) |
| } |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| unsafe { |
| // Similar problem as transform(), but we need to use ptr::read since |
| // the compiler isn't sure of the sizes |
| let this = mem::ManuallyDrop::new(self); |
| let ptr: *const Self::Output = (&*this as *const Self).cast(); |
| ptr::read(ptr) |
| } |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| #[allow(clippy::transmute_ptr_to_ptr)] |
| unsafe impl<'a, K, V> Yokeable<'a> for ZeroMapBorrowed<'static, K, V> |
| where |
| K: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| &'static <K as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>, |
| &'static <V as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>, |
| { |
| type Output = ZeroMapBorrowed<'a, K, V>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| unsafe { |
| // Unfortunately, because K and V are generic, rustc is |
| // unaware that these are covariant types, and cannot perform this cast automatically. |
| // We transmute it instead, and enforce the lack of a lifetime with the `K, V: 'static` bound |
| mem::transmute::<&Self, &Self::Output>(self) |
| } |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| unsafe { |
| // Similar problem as transform(), but we need to use ptr::read since |
| // the compiler isn't sure of the sizes |
| let this = mem::ManuallyDrop::new(self); |
| let ptr: *const Self::Output = (&*this as *const Self).cast(); |
| ptr::read(ptr) |
| } |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| #[allow(clippy::transmute_ptr_to_ptr)] |
| unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2d<'static, K0, K1, V> |
| where |
| K0: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| K1: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| <K0 as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>, |
| <K1 as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>, |
| <V as ZeroMapKV<'static>>::Container: for<'b> Yokeable<'b>, |
| { |
| type Output = ZeroMap2d<'a, K0, K1, V>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| unsafe { |
| // Unfortunately, because K and V are generic, rustc is |
| // unaware that these are covariant types, and cannot perform this cast automatically. |
| // We transmute it instead, and enforce the lack of a lifetime with the `K0, K1, V: 'static` bound |
| mem::transmute::<&Self, &Self::Output>(self) |
| } |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| unsafe { |
| // Similar problem as transform(), but we need to use ptr::read since |
| // the compiler isn't sure of the sizes |
| let this = mem::ManuallyDrop::new(self); |
| let ptr: *const Self::Output = (&*this as *const Self).cast(); |
| ptr::read(ptr) |
| } |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate |
| #[allow(clippy::transmute_ptr_to_ptr)] |
| unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2dBorrowed<'static, K0, K1, V> |
| where |
| K0: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| K1: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| V: 'static + for<'b> ZeroMapKV<'b> + ?Sized, |
| &'static <K0 as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>, |
| &'static <K1 as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>, |
| &'static <V as ZeroMapKV<'static>>::Slice: for<'b> Yokeable<'b>, |
| { |
| type Output = ZeroMap2dBorrowed<'a, K0, K1, V>; |
| #[inline] |
| fn transform(&'a self) -> &'a Self::Output { |
| unsafe { |
| // Unfortunately, because K and V are generic, rustc is |
| // unaware that these are covariant types, and cannot perform this cast automatically. |
| // We transmute it instead, and enforce the lack of a lifetime with the `K0, K1, V: 'static` bound |
| mem::transmute::<&Self, &Self::Output>(self) |
| } |
| } |
| #[inline] |
| fn transform_owned(self) -> Self::Output { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| unsafe { |
| // Similar problem as transform(), but we need to use ptr::read since |
| // the compiler isn't sure of the sizes |
| let this = mem::ManuallyDrop::new(self); |
| let ptr: *const Self::Output = (&*this as *const Self).cast(); |
| ptr::read(ptr) |
| } |
| } |
| #[inline] |
| unsafe fn make(from: Self::Output) -> Self { |
| debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>()); |
| let from = mem::ManuallyDrop::new(from); |
| let ptr: *const Self = (&*from as *const Self::Output).cast(); |
| ptr::read(ptr) |
| } |
| #[inline] |
| fn transform_mut<F>(&'a mut self, f: F) |
| where |
| F: 'static + for<'b> FnOnce(&'b mut Self::Output), |
| { |
| unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) } |
| } |
| } |
| |
| #[cfg(test)] |
| #[allow(non_camel_case_types, non_snake_case)] |
| mod test { |
| use super::*; |
| use crate::{vecs::FlexZeroSlice, VarZeroSlice, ZeroSlice}; |
| use databake::*; |
| |
| // Note: The following derives cover Yoke as well as Serde and databake. These may partially |
| // duplicate tests elsewhere in this crate, but they are here for completeness. |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_ZeroVec<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroVec<'data, u16>, |
| } |
| |
| #[test] |
| #[ignore] // https://github.com/rust-lang/rust/issues/98906 |
| fn bake_ZeroVec() { |
| test_bake!( |
| DeriveTest_ZeroVec<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroVec { |
| _data: crate::ZeroVec::new(), |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_ZeroSlice<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: &'data ZeroSlice<u16>, |
| } |
| |
| #[test] |
| fn bake_ZeroSlice() { |
| test_bake!( |
| DeriveTest_ZeroSlice<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroSlice { |
| _data: crate::ZeroSlice::new_empty(), |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_FlexZeroVec<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: FlexZeroVec<'data>, |
| } |
| |
| #[test] |
| #[ignore] // https://github.com/rust-lang/rust/issues/98906 |
| fn bake_FlexZeroVec() { |
| test_bake!( |
| DeriveTest_FlexZeroVec<'static>, |
| crate::yoke_impls::test::DeriveTest_FlexZeroVec { |
| _data: unsafe { crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(b"\x01") } |
| .as_flexzerovec(), |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_FlexZeroSlice<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: &'data FlexZeroSlice, |
| } |
| |
| #[test] |
| fn bake_FlexZeroSlice() { |
| test_bake!( |
| DeriveTest_FlexZeroSlice<'static>, |
| crate::yoke_impls::test::DeriveTest_FlexZeroSlice { |
| _data: unsafe { crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(b"\x01\0") }, |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_VarZeroVec<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: VarZeroVec<'data, str>, |
| } |
| |
| #[test] |
| fn bake_VarZeroVec() { |
| test_bake!( |
| DeriveTest_VarZeroVec<'static>, |
| crate::yoke_impls::test::DeriveTest_VarZeroVec { |
| _data: crate::VarZeroVec::new(), |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| struct DeriveTest_VarZeroSlice<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: &'data VarZeroSlice<str>, |
| } |
| |
| #[test] |
| fn bake_VarZeroSlice() { |
| test_bake!( |
| DeriveTest_VarZeroSlice<'static>, |
| crate::yoke_impls::test::DeriveTest_VarZeroSlice { |
| _data: crate::VarZeroSlice::new_empty() |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| #[yoke(prove_covariance_manually)] |
| struct DeriveTest_ZeroMap<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroMap<'data, [u8], str>, |
| } |
| |
| #[test] |
| fn bake_ZeroMap() { |
| test_bake!( |
| DeriveTest_ZeroMap<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroMap { |
| _data: unsafe { |
| #[allow(unused_unsafe)] |
| crate::ZeroMap::from_parts_unchecked( |
| crate::VarZeroVec::new(), |
| crate::VarZeroVec::new(), |
| ) |
| }, |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| #[yoke(prove_covariance_manually)] |
| struct DeriveTest_ZeroMapBorrowed<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroMapBorrowed<'data, [u8], str>, |
| } |
| |
| #[test] |
| fn bake_ZeroMapBorrowed() { |
| test_bake!( |
| DeriveTest_ZeroMapBorrowed<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroMapBorrowed { |
| _data: unsafe { |
| #[allow(unused_unsafe)] |
| crate::maps::ZeroMapBorrowed::from_parts_unchecked( |
| crate::VarZeroSlice::new_empty(), |
| crate::VarZeroSlice::new_empty(), |
| ) |
| }, |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| #[yoke(prove_covariance_manually)] |
| struct DeriveTest_ZeroMapWithULE<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroMap<'data, ZeroSlice<u32>, str>, |
| } |
| |
| #[test] |
| fn bake_ZeroMapWithULE() { |
| test_bake!( |
| DeriveTest_ZeroMapWithULE<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroMapWithULE { |
| _data: unsafe { |
| #[allow(unused_unsafe)] |
| crate::ZeroMap::from_parts_unchecked( |
| crate::VarZeroVec::new(), |
| crate::VarZeroVec::new(), |
| ) |
| }, |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable, zerofrom::ZeroFrom)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| #[yoke(prove_covariance_manually)] |
| struct DeriveTest_ZeroMap2d<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroMap2d<'data, u16, u16, str>, |
| } |
| |
| #[test] |
| fn bake_ZeroMap2d() { |
| test_bake!( |
| DeriveTest_ZeroMap2d<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroMap2d { |
| _data: unsafe { |
| #[allow(unused_unsafe)] |
| crate::ZeroMap2d::from_parts_unchecked( |
| crate::ZeroVec::new(), |
| crate::ZeroVec::new(), |
| crate::ZeroVec::new(), |
| crate::VarZeroVec::new(), |
| ) |
| }, |
| }, |
| zerovec, |
| ); |
| } |
| |
| #[derive(yoke::Yokeable)] |
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] |
| #[cfg_attr(feature = "databake", derive(databake::Bake), databake(path = zerovec::yoke_impls::test))] |
| #[yoke(prove_covariance_manually)] |
| struct DeriveTest_ZeroMap2dBorrowed<'data> { |
| #[cfg_attr(feature = "serde", serde(borrow))] |
| _data: ZeroMap2dBorrowed<'data, u16, u16, str>, |
| } |
| |
| #[test] |
| fn bake_ZeroMap2dBorrowed() { |
| test_bake!( |
| DeriveTest_ZeroMap2dBorrowed<'static>, |
| crate::yoke_impls::test::DeriveTest_ZeroMap2dBorrowed { |
| _data: unsafe { |
| #[allow(unused_unsafe)] |
| crate::maps::ZeroMap2dBorrowed::from_parts_unchecked( |
| crate::ZeroSlice::new_empty(), |
| crate::ZeroSlice::new_empty(), |
| crate::ZeroSlice::new_empty(), |
| crate::VarZeroSlice::new_empty(), |
| ) |
| }, |
| }, |
| zerovec, |
| ); |
| } |
| } |