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 //! Types to enable polymorphic carts. 6 7 use crate::CloneableCart; 8 9 use core::ops::Deref; 10 use stable_deref_trait::StableDeref; 11 12 /// A cart that can be one type or the other. Enables ergonomic polymorphic carts. 13 /// 14 /// `EitherCart` enables yokes originating from different data sources and therefore 15 /// having different cart types to be merged into the same yoke type, but still being 16 /// able to recover the original cart type if necessary. 17 /// 18 /// All relevant Cart traits are implemented for `EitherCart`, and carts can be 19 /// safely wrapped in an `EitherCart`. 20 /// 21 /// Also see [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart). 22 /// 23 /// # Examples 24 /// 25 /// ``` 26 /// use std::rc::Rc; 27 /// use yoke::either::EitherCart; 28 /// use yoke::Yoke; 29 /// 30 /// let y1: Yoke<&'static str, Rc<str>> = 31 /// Yoke::attach_to_zero_copy_cart("reference counted hello world".into()); 32 /// 33 /// let y2: Yoke<&'static str, &str> = Yoke::attach_to_zero_copy_cart("borrowed hello world"); 34 /// 35 /// type CombinedYoke<'a> = Yoke<&'static str, EitherCart<Rc<str>, &'a str>>; 36 /// 37 /// // Both yokes can be combined into a single yoke type despite different carts 38 /// let y3: CombinedYoke = y1.wrap_cart_in_either_a(); 39 /// let y4: CombinedYoke = y2.wrap_cart_in_either_b(); 40 /// 41 /// assert_eq!(*y3.get(), "reference counted hello world"); 42 /// assert_eq!(*y4.get(), "borrowed hello world"); 43 /// 44 /// // The resulting yoke is cloneable if both cart types implement CloneableCart 45 /// let y5 = y4.clone(); 46 /// assert_eq!(*y5.get(), "borrowed hello world"); 47 /// ``` 48 #[derive(Clone, PartialEq, Eq, Debug)] 49 #[allow(clippy::exhaustive_enums)] // stable 50 pub enum EitherCart<C0, C1> { 51 A(C0), 52 B(C1), 53 } 54 55 impl<C0, C1, T> Deref for EitherCart<C0, C1> 56 where 57 C0: Deref<Target = T>, 58 C1: Deref<Target = T>, 59 { 60 type Target = T; deref(&self) -> &T61 fn deref(&self) -> &T { 62 use EitherCart::*; 63 match self { 64 A(a) => a.deref(), 65 B(b) => b.deref(), 66 } 67 } 68 } 69 70 // Safety: Safe because both sub-types implement the trait. 71 unsafe impl<C0, C1, T> StableDeref for EitherCart<C0, C1> 72 where 73 C0: StableDeref, 74 C1: StableDeref, 75 C0: Deref<Target = T>, 76 C1: Deref<Target = T>, 77 { 78 } 79 80 // Safety: Safe because both sub-types implement the trait. 81 unsafe impl<C0, C1> CloneableCart for EitherCart<C0, C1> 82 where 83 C0: CloneableCart, 84 C1: CloneableCart, 85 { 86 } 87