/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_properties-2.2.0/src/emoji.rs
Line | Count | Source |
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 crate::provider::*; |
6 | | use icu_collections::codepointinvliststringlist::CodePointInversionListAndStringList; |
7 | | use icu_provider::marker::ErasedMarker; |
8 | | use icu_provider::prelude::*; |
9 | | |
10 | | /// A wrapper around `UnicodeSet` data (characters and strings) |
11 | | #[derive(Debug)] |
12 | | pub struct EmojiSetData { |
13 | | data: DataPayload<ErasedMarker<PropertyUnicodeSet<'static>>>, |
14 | | } |
15 | | |
16 | | impl EmojiSetData { |
17 | | /// Creates a new [`EmojiSetDataBorrowed`] for a [`EmojiSet`]. |
18 | | /// |
19 | | /// See the documentation on [`EmojiSet`] implementations for details. |
20 | | /// |
21 | | /// ✨ *Enabled with the `compiled_data` Cargo feature.* |
22 | | /// |
23 | | /// [📚 Help choosing a constructor](icu_provider::constructors) |
24 | | #[cfg(feature = "compiled_data")] |
25 | | #[expect(clippy::new_ret_no_self)] |
26 | 0 | pub const fn new<P: EmojiSet>() -> EmojiSetDataBorrowed<'static> { |
27 | 0 | EmojiSetDataBorrowed::new::<P>() |
28 | 0 | } |
29 | | |
30 | | #[cfg(feature = "serde")] |
31 | | #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER, Self::new)] |
32 | | pub fn try_new_with_buffer_provider<P: EmojiSet>( |
33 | | provider: &(impl BufferProvider + ?Sized), |
34 | | ) -> Result<EmojiSetData, DataError> { |
35 | | use icu_provider::buf::AsDeserializingBufferProvider; |
36 | | Self::try_new_unstable::<P>(&provider.as_deserializing()) |
37 | | } |
38 | | |
39 | | /// A version of `new()` that uses custom data provided by a [`DataProvider`]. |
40 | | /// |
41 | | /// Note that this will return an owned version of the data. Functionality is available on |
42 | | /// the borrowed version, accessible through [`EmojiSetData::as_borrowed`]. |
43 | 0 | pub fn try_new_unstable<P: EmojiSet>( |
44 | 0 | provider: &(impl DataProvider<P::DataMarker> + ?Sized), |
45 | 0 | ) -> Result<EmojiSetData, DataError> { |
46 | 0 | Ok(EmojiSetData::from_data( |
47 | 0 | provider.load(Default::default())?.payload, |
48 | | )) |
49 | 0 | } |
50 | | |
51 | | /// Construct a borrowed version of this type that can be queried. |
52 | | /// |
53 | | /// This avoids a potential small underlying cost per API call (ex: `contains()`) by consolidating it |
54 | | /// up front. |
55 | | #[inline] |
56 | 0 | pub fn as_borrowed(&self) -> EmojiSetDataBorrowed<'_> { |
57 | 0 | EmojiSetDataBorrowed { |
58 | 0 | set: self.data.get(), |
59 | 0 | } |
60 | 0 | } |
61 | | |
62 | | /// Construct a new one from loaded data |
63 | | /// |
64 | | /// Typically it is preferable to use getters instead |
65 | 0 | pub(crate) fn from_data<M>(data: DataPayload<M>) -> Self |
66 | 0 | where |
67 | 0 | M: DynamicDataMarker<DataStruct = PropertyUnicodeSet<'static>>, |
68 | | { |
69 | 0 | Self { data: data.cast() } |
70 | 0 | } |
71 | | |
72 | | /// Construct a new owned [`CodePointInversionListAndStringList`] |
73 | 0 | pub fn from_code_point_inversion_list_string_list( |
74 | 0 | set: CodePointInversionListAndStringList<'static>, |
75 | 0 | ) -> Self { |
76 | 0 | let set = PropertyUnicodeSet::from_code_point_inversion_list_string_list(set); |
77 | 0 | EmojiSetData::from_data( |
78 | 0 | DataPayload::<ErasedMarker<PropertyUnicodeSet<'static>>>::from_owned(set), |
79 | | ) |
80 | 0 | } |
81 | | |
82 | | /// Convert this type to a [`CodePointInversionListAndStringList`] as a borrowed value. |
83 | | /// |
84 | | /// The data backing this is extensible and supports multiple implementations. |
85 | | /// Currently it is always [`CodePointInversionListAndStringList`]; however in the future more backends may be |
86 | | /// added, and users may select which at data generation time. |
87 | | /// |
88 | | /// This method returns an `Option` in order to return `None` when the backing data provider |
89 | | /// cannot return a [`CodePointInversionListAndStringList`], or cannot do so within the expected constant time |
90 | | /// constraint. |
91 | 0 | pub fn as_code_point_inversion_list_string_list( |
92 | 0 | &self, |
93 | 0 | ) -> Option<&CodePointInversionListAndStringList<'_>> { |
94 | 0 | self.data.get().as_code_point_inversion_list_string_list() |
95 | 0 | } |
96 | | |
97 | | /// Convert this type to a [`CodePointInversionListAndStringList`], borrowing if possible, |
98 | | /// otherwise allocating a new [`CodePointInversionListAndStringList`]. |
99 | | /// |
100 | | /// The data backing this is extensible and supports multiple implementations. |
101 | | /// Currently it is always [`CodePointInversionListAndStringList`]; however in the future more backends may be |
102 | | /// added, and users may select which at data generation time. |
103 | | /// |
104 | | /// The performance of the conversion to this specific return type will vary |
105 | | /// depending on the data structure that is backing `self`. |
106 | 0 | pub fn to_code_point_inversion_list_string_list( |
107 | 0 | &self, |
108 | 0 | ) -> CodePointInversionListAndStringList<'_> { |
109 | 0 | self.data.get().to_code_point_inversion_list_string_list() |
110 | 0 | } |
111 | | } |
112 | | |
113 | | /// A borrowed wrapper around code point set data, returned by |
114 | | /// [`EmojiSetData::as_borrowed()`]. More efficient to query. |
115 | | #[derive(Clone, Copy, Debug)] |
116 | | pub struct EmojiSetDataBorrowed<'a> { |
117 | | set: &'a PropertyUnicodeSet<'a>, |
118 | | } |
119 | | |
120 | | impl EmojiSetDataBorrowed<'_> { |
121 | | /// Check if the set contains the string. Strings consisting of one character |
122 | | /// are treated as a character/code point. |
123 | | /// |
124 | | /// This matches ICU behavior for ICU's `UnicodeSet`. |
125 | | #[inline] |
126 | 0 | pub fn contains_str(self, s: &str) -> bool { |
127 | 0 | self.set.contains_str(s) |
128 | 0 | } |
129 | | |
130 | | /// See [`Self::contains_str`]. |
131 | | #[inline] |
132 | 0 | pub fn contains_utf8(self, s: &[u8]) -> bool { |
133 | 0 | self.set.contains_utf8(s) |
134 | 0 | } |
135 | | |
136 | | /// Check if the set contains the code point. |
137 | | #[inline] |
138 | 0 | pub fn contains(self, ch: char) -> bool { |
139 | 0 | self.set.contains(ch) |
140 | 0 | } |
141 | | |
142 | | /// See [`Self::contains`]. |
143 | | #[inline] |
144 | 0 | pub fn contains32(self, cp: u32) -> bool { |
145 | 0 | self.set.contains32(cp) |
146 | 0 | } |
147 | | } |
148 | | |
149 | | impl EmojiSetDataBorrowed<'static> { |
150 | | /// Creates a new [`EmojiSetDataBorrowed`] for a [`EmojiSet`]. |
151 | | /// |
152 | | /// See the documentation on [`EmojiSet`] implementations for details. |
153 | | /// |
154 | | /// ✨ *Enabled with the `compiled_data` Cargo feature.* |
155 | | /// |
156 | | /// [📚 Help choosing a constructor](icu_provider::constructors) |
157 | | #[inline] |
158 | | #[cfg(feature = "compiled_data")] |
159 | 0 | pub const fn new<P: EmojiSet>() -> Self { |
160 | 0 | EmojiSetDataBorrowed { set: P::SINGLETON } |
161 | 0 | } |
162 | | |
163 | | /// Cheaply converts a [`EmojiSetDataBorrowed<'static>`] into a [`EmojiSetData`]. |
164 | | /// |
165 | | /// Note: Due to branching and indirection, using [`EmojiSetData`] might inhibit some |
166 | | /// compile-time optimizations that are possible with [`EmojiSetDataBorrowed`]. |
167 | 0 | pub const fn static_to_owned(self) -> EmojiSetData { |
168 | 0 | EmojiSetData { |
169 | 0 | data: DataPayload::from_static_ref(self.set), |
170 | 0 | } |
171 | 0 | } |
172 | | } |
173 | | |
174 | | /// An Emoji set as defined by [`Unicode Technical Standard #51`](https://unicode.org/reports/tr51/#Emoji_Sets>). |
175 | | /// |
176 | | /// <div class="stab unstable"> |
177 | | /// 🚫 This trait is sealed; it cannot be implemented by user code. If an API requests an item that implements this |
178 | | /// trait, please consider using a type from the implementors listed below. |
179 | | /// </div> |
180 | | pub trait EmojiSet: crate::private::Sealed + Sized { |
181 | | #[doc(hidden)] |
182 | | type DataMarker: DataMarker<DataStruct = PropertyUnicodeSet<'static>>; |
183 | | #[doc(hidden)] |
184 | | #[cfg(feature = "compiled_data")] |
185 | | const SINGLETON: &'static PropertyUnicodeSet<'static>; |
186 | | /// The name of this property |
187 | | const NAME: &'static [u8]; |
188 | | /// The abbreviated name of this property, if it exists, otherwise the name |
189 | | const SHORT_NAME: &'static [u8]; |
190 | | |
191 | | /// Convenience method for `EmojiSetData::new().contains(ch)` |
192 | | /// |
193 | | /// ✨ *Enabled with the `compiled_data` Cargo feature.* |
194 | | #[cfg(feature = "compiled_data")] |
195 | 0 | fn for_char(ch: char) -> bool { |
196 | 0 | EmojiSetData::new::<Self>().contains(ch) |
197 | 0 | } |
198 | | |
199 | | /// Convenience method for `EmojiSetData::new().contains_str(s)` |
200 | | /// |
201 | | /// ✨ *Enabled with the `compiled_data` Cargo feature.* |
202 | | #[cfg(feature = "compiled_data")] |
203 | 0 | fn for_str(s: &str) -> bool { |
204 | 0 | EmojiSetData::new::<Self>().contains_str(s) |
205 | 0 | } |
206 | | } |