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 use zerovec::ule::VarULE; 6 7 #[cfg(feature = "alloc")] 8 use zerovec::{maps::ZeroMapKV, ZeroMap2d}; 9 10 /// A trait that associates a [`VarULE`] type with a data struct. 11 /// 12 /// Some data structs can be represented compactly as a single [`VarULE`], 13 /// such as `str` or a packed pattern. This trait allows for data providers 14 /// to use optimizations for such types. 15 /// 16 /// ❗ Not all data structs benefit from this optimization. It works best when the 17 /// data struct is multiplied across a large number of data marker attributes. 18 /// 19 /// Both [`MaybeAsVarULE`] and [`MaybeEncodeAsVarULE`] should be implemented 20 /// on all data structs. The [`data_struct!`] macro provides an impl. 21 pub trait MaybeAsVarULE { 22 /// The [`VarULE`] type for this data struct, or `[()]` 23 /// if it cannot be represented as [`VarULE`]. 24 type EncodedStruct: ?Sized + VarULE; 25 } 26 27 /// Export-only trait associated with [`MaybeAsVarULE`]. See that trait 28 /// for additional details. 29 // #[cfg(feature = "export")] // TODO(#5230): Enable feature gating 30 pub trait MaybeEncodeAsVarULE: MaybeAsVarULE { 31 /// Returns the [`MaybeAsVarULE::EncodedStruct`] that represents this data struct, 32 /// or `None` if the data struct does not support this representation. maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct>33 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct>; 34 } 35 36 /// Implements required traits on data structs, such as [`MaybeEncodeAsVarULE`]. 37 #[macro_export] 38 macro_rules! __data_struct { 39 (<$generic:ident: $bound:tt> $ty:path $(, $(#[$attr:meta])*)?) => { 40 impl<$generic: $bound> $crate::ule::MaybeAsVarULE for $ty { 41 type EncodedStruct = [()]; 42 } 43 $($(#[$attr])*)? 44 impl<$generic: $bound> $crate::ule::MaybeEncodeAsVarULE for $ty { 45 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct> { 46 None 47 } 48 } 49 }; 50 ($ty:path $(, $(#[$attr:meta])*)?) => { 51 impl $crate::ule::MaybeAsVarULE for $ty { 52 type EncodedStruct = [()]; 53 } 54 $($(#[$attr])*)? 55 impl $crate::ule::MaybeEncodeAsVarULE for $ty { 56 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct> { 57 None 58 } 59 } 60 }; 61 ( 62 $ty:ty, 63 varule: $varule:ty, 64 $(#[$attr:meta])* 65 encode_as_varule: $encode_as_varule:expr 66 ) => { 67 impl<'data> $crate::ule::MaybeAsVarULE for $ty { 68 type EncodedStruct = $varule; 69 } 70 $(#[$attr])* 71 impl<'data> $crate::ule::MaybeEncodeAsVarULE for $ty { 72 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct> { 73 // Workaround for <https://rust-lang.github.io/rfcs/3216-closure-lifetime-binder.html> 74 fn bind_lifetimes<F>(f: F) -> F where F: for<'data> Fn(&'data $ty) -> &'data $varule { f } 75 Some(bind_lifetimes($encode_as_varule)(self)) 76 } 77 } 78 }; 79 } 80 #[doc(inline)] 81 pub use __data_struct as data_struct; 82 83 //=== Standard impls ===// 84 85 #[cfg(feature = "alloc")] 86 impl<'a, K0, K1, V> MaybeAsVarULE for ZeroMap2d<'a, K0, K1, V> 87 where 88 K0: ZeroMapKV<'a>, 89 K1: ZeroMapKV<'a>, 90 V: ZeroMapKV<'a>, 91 K0: ?Sized, 92 K1: ?Sized, 93 V: ?Sized, 94 { 95 type EncodedStruct = [()]; 96 } 97 98 #[cfg(feature = "alloc")] 99 impl<'a, K0, K1, V> MaybeEncodeAsVarULE for ZeroMap2d<'a, K0, K1, V> 100 where 101 K0: ZeroMapKV<'a>, 102 K1: ZeroMapKV<'a>, 103 V: ZeroMapKV<'a>, 104 K0: ?Sized, 105 K1: ?Sized, 106 V: ?Sized, 107 { maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct>108 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct> { 109 None 110 } 111 } 112 113 impl<T, const N: usize> MaybeAsVarULE for [T; N] { 114 type EncodedStruct = [()]; 115 } 116 117 impl<T, const N: usize> MaybeEncodeAsVarULE for [T; N] { maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct>118 fn maybe_encode_as_varule(&self) -> Option<&Self::EncodedStruct> { 119 None 120 } 121 } 122