• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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