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