1#[allow(unused_imports)] use alloc::boxed::Box;
7use icu_provider::prelude::*;
8#[allow(unused_imports)] use icu_provider::MaybeSendSync;
10use icu_provider_adapters::empty::EmptyDataProvider;
11#[allow(unused_imports)] use yoke::{trait_hack::YokeTraitHack, Yokeable};
13#[allow(unused_imports)] use zerofrom::ZeroFrom;
15
16pub enum ICU4XDataProviderInner {
17 Destroyed,
18 Empty,
19 #[cfg(feature = "compiled_data")]
20 Compiled,
21 #[cfg(feature = "buffer_provider")]
22 Buffer(Box<dyn BufferProvider + 'static>),
23}
24
25#[diplomat::bridge]
26pub mod ffi {
27 use super::ICU4XDataProviderInner;
28 use crate::errors::ffi::ICU4XError;
29 use alloc::boxed::Box;
30 #[allow(unused_imports)] use icu_provider_adapters::fallback::LocaleFallbackProvider;
32 #[allow(unused_imports)] use icu_provider_adapters::fork::predicates::MissingLocalePredicate;
34
35 #[diplomat::opaque]
36 #[diplomat::rust_link(icu_provider, Mod)]
38 pub struct ICU4XDataProvider(pub ICU4XDataProviderInner);
39
40 #[cfg(feature = "buffer_provider")]
41 fn convert_buffer_provider<D: icu_provider::BufferProvider + 'static>(
42 x: D,
43 ) -> ICU4XDataProvider {
44 ICU4XDataProvider(super::ICU4XDataProviderInner::Buffer(Box::new(x)))
45 }
46
47 impl ICU4XDataProvider {
48 #[cfg(feature = "compiled_data")]
55 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "compiled")]
56 pub fn create_compiled() -> Box<ICU4XDataProvider> {
57 Box::new(Self(ICU4XDataProviderInner::Compiled))
58 }
59
60 #[diplomat::rust_link(icu_provider_fs::FsDataProvider, Struct)]
64 #[cfg(all(
65 feature = "provider_fs",
66 not(any(target_arch = "wasm32", target_os = "none"))
67 ))]
68 #[diplomat::attr(dart, disable)]
69 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "fs")]
70 pub fn create_fs(path: &DiplomatStr) -> Result<Box<ICU4XDataProvider>, ICU4XError> {
71 Ok(Box::new(convert_buffer_provider(
72 icu_provider_fs::FsDataProvider::try_new(
73 core::str::from_utf8(path)
75 .map_err(|e| ICU4XError::DataIoError.log_original(&e))?,
76 )?,
77 )))
78 }
79
80 #[cfg(all(
84 feature = "provider_test",
85 any(feature = "any_provider", feature = "buffer_provider")
86 ))]
87 #[diplomat::attr(supports = constructors, disable)]
88 pub fn create_test() -> Box<ICU4XDataProvider> {
89 Self::create_compiled()
90 }
91
92 #[diplomat::rust_link(icu_provider_blob::BlobDataProvider, Struct)]
94 #[cfg(feature = "buffer_provider")]
95 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_byte_slice")]
96 pub fn create_from_byte_slice(
97 blob: &'static [DiplomatByte],
98 ) -> Result<Box<ICU4XDataProvider>, ICU4XError> {
99 Ok(Box::new(convert_buffer_provider(
100 icu_provider_blob::BlobDataProvider::try_new_from_static_blob(blob)?,
101 )))
102 }
103
104 #[diplomat::rust_link(icu_provider_adapters::empty::EmptyDataProvider, Struct)]
106 #[diplomat::rust_link(
107 icu_provider_adapters::empty::EmptyDataProvider::new,
108 FnInStruct,
109 hidden
110 )]
111 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "empty")]
112 pub fn create_empty() -> Box<ICU4XDataProvider> {
113 Box::new(ICU4XDataProvider(ICU4XDataProviderInner::Empty))
114 }
115
116 #[diplomat::rust_link(icu_provider_adapters::fork::ForkByKeyProvider, Typedef)]
125 #[diplomat::rust_link(
126 icu_provider_adapters::fork::predicates::MissingDataKeyPredicate,
127 Struct,
128 hidden
129 )]
130 pub fn fork_by_key(&mut self, other: &mut ICU4XDataProvider) -> Result<(), ICU4XError> {
131 #[allow(unused_imports)]
132 use ICU4XDataProviderInner::*;
133 *self = match (
134 core::mem::replace(&mut self.0, Destroyed),
135 core::mem::replace(&mut other.0, Destroyed),
136 ) {
137 (Destroyed, _) | (_, Destroyed) => Err(icu_provider::DataError::custom(
138 "This provider has been destroyed",
139 ))?,
140 #[cfg(feature = "compiled_data")]
141 (Compiled, _) | (_, Compiled) => Err(icu_provider::DataError::custom(
142 "The compiled provider cannot be modified",
143 ))?,
144 (Empty, Empty) => ICU4XDataProvider(ICU4XDataProviderInner::Empty),
145 #[cfg(feature = "buffer_provider")]
146 (Empty, b) | (b, Empty) => ICU4XDataProvider(b),
147 #[cfg(feature = "buffer_provider")]
148 (Buffer(a), Buffer(b)) => convert_buffer_provider(
149 icu_provider_adapters::fork::ForkByKeyProvider::new(a, b),
150 ),
151 };
152 Ok(())
153 }
154
155 #[diplomat::rust_link(
157 icu_provider_adapters::fork::predicates::MissingLocalePredicate,
158 Struct
159 )]
160 pub fn fork_by_locale(&mut self, other: &mut ICU4XDataProvider) -> Result<(), ICU4XError> {
161 #[allow(unused_imports)]
162 use ICU4XDataProviderInner::*;
163 *self = match (
164 core::mem::replace(&mut self.0, Destroyed),
165 core::mem::replace(&mut other.0, Destroyed),
166 ) {
167 (Destroyed, _) | (_, Destroyed) => Err(icu_provider::DataError::custom(
168 "This provider has been destroyed",
169 ))?,
170 #[cfg(feature = "compiled_data")]
171 (Compiled, _) | (_, Compiled) => Err(icu_provider::DataError::custom(
172 "The compiled provider cannot be modified",
173 ))?,
174 (Empty, Empty) => ICU4XDataProvider(ICU4XDataProviderInner::Empty),
175 #[cfg(feature = "buffer_provider")]
176 (Empty, b) | (b, Empty) => ICU4XDataProvider(b),
177 #[cfg(feature = "buffer_provider")]
178 (Buffer(a), Buffer(b)) => convert_buffer_provider(
179 icu_provider_adapters::fork::ForkByErrorProvider::new_with_predicate(
180 a,
181 b,
182 MissingLocalePredicate,
183 ),
184 ),
185 };
186 Ok(())
187 }
188
189 #[diplomat::rust_link(
193 icu_provider_adapters::fallback::LocaleFallbackProvider::try_new,
194 FnInStruct
195 )]
196 #[diplomat::rust_link(
197 icu_provider_adapters::fallback::LocaleFallbackProvider,
198 Struct,
199 compact
200 )]
201 pub fn enable_locale_fallback(&mut self) -> Result<(), ICU4XError> {
202 use ICU4XDataProviderInner::*;
203 *self = match core::mem::replace(&mut self.0, Destroyed) {
204 Destroyed => Err(icu_provider::DataError::custom(
205 "This provider has been destroyed",
206 ))?,
207 #[cfg(feature = "compiled_data")]
208 Compiled => Err(icu_provider::DataError::custom(
209 "The compiled provider cannot be modified",
210 ))?,
211 Empty => Err(icu_provider::DataErrorKind::MissingDataKey.into_error())?,
212 #[cfg(feature = "buffer_provider")]
213 Buffer(inner) => convert_buffer_provider(
214 LocaleFallbackProvider::try_new_with_buffer_provider(inner)?,
215 ),
216 };
217 Ok(())
218 }
219
220 #[diplomat::rust_link(
221 icu_provider_adapters::fallback::LocaleFallbackProvider::new_with_fallbacker,
222 FnInStruct
223 )]
224 #[diplomat::rust_link(
225 icu_provider_adapters::fallback::LocaleFallbackProvider,
226 Struct,
227 compact
228 )]
229 #[allow(unused_variables)] #[cfg(feature = "icu_locid_transform")]
231 pub fn enable_locale_fallback_with(
232 &mut self,
233 fallbacker: &crate::fallbacker::ffi::ICU4XLocaleFallbacker,
234 ) -> Result<(), ICU4XError> {
235 use ICU4XDataProviderInner::*;
236 *self = match core::mem::replace(&mut self.0, Destroyed) {
237 Destroyed => Err(icu_provider::DataError::custom(
238 "This provider has been destroyed",
239 ))?,
240 #[cfg(feature = "compiled_data")]
241 Compiled => Err(icu_provider::DataError::custom(
242 "The compiled provider cannot be modified",
243 ))?,
244 Empty => Err(icu_provider::DataErrorKind::MissingDataKey.into_error())?,
245 #[cfg(feature = "buffer_provider")]
246 Buffer(inner) => convert_buffer_provider(
247 LocaleFallbackProvider::new_with_fallbacker(inner, fallbacker.0.clone()),
248 ),
249 };
250 Ok(())
251 }
252 }
253}
254
255macro_rules! load {
256 () => {
257 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
258 use ICU4XDataProviderInner::*;
259 match self {
260 Destroyed => Err(icu_provider::DataError::custom(
261 "This provider has been destroyed",
262 ))?,
263 Empty => EmptyDataProvider::new().load(req),
264 #[cfg(feature = "buffer_provider")]
265 Buffer(buffer_provider) => buffer_provider.as_deserializing().load(req),
266 #[cfg(feature = "compiled_data")]
267 Compiled => unreachable!(),
268 }
269 }
270 };
271}
272
273#[macro_export]
274macro_rules! call_constructor {
275 ($compiled:path [$pre_transform:ident => $transform:expr], $any:path, $buffer:path, $provider:expr $(, $args:expr)* $(,)?) => {
276 match &$provider.0 {
277 $crate::provider::ICU4XDataProviderInner::Destroyed => Err(icu_provider::DataError::custom(
278 "This provider has been destroyed",
279 ))?,
280 $crate::provider::ICU4XDataProviderInner::Empty => $any(&icu_provider_adapters::empty::EmptyDataProvider::new(), $($args,)*),
281 #[cfg(feature = "buffer_provider")]
282 $crate::provider::ICU4XDataProviderInner::Buffer(buffer_provider) => $buffer(buffer_provider, $($args,)*),
283 #[cfg(feature = "compiled_data")]
284 $crate::provider::ICU4XDataProviderInner::Compiled => { let $pre_transform = $compiled($($args,)*); $transform },
285 }
286 };
287 ($compiled:path, $any:path, $buffer:path, $provider:expr $(, $args:expr)* $(,)?) => {
288 match &$provider.0 {
289 $crate::provider::ICU4XDataProviderInner::Destroyed => Err(icu_provider::DataError::custom(
290 "This provider has been destroyed",
291 ))?,
292 $crate::provider::ICU4XDataProviderInner::Empty => $any(&icu_provider_adapters::empty::EmptyDataProvider::new(), $($args,)*),
293 #[cfg(feature = "buffer_provider")]
294 $crate::provider::ICU4XDataProviderInner::Buffer(buffer_provider) => $buffer(buffer_provider, $($args,)*),
295 #[cfg(feature = "compiled_data")]
296 $crate::provider::ICU4XDataProviderInner::Compiled => $compiled($($args,)*),
297 }
298 };
299}
300
301#[macro_export]
302macro_rules! call_constructor_unstable {
303 ($compiled:path [$pre_transform:ident => $transform:expr], $unstable:path, $provider:expr $(, $args:expr)* $(,)?) => {
304 match &$provider.0 {
305 $crate::provider::ICU4XDataProviderInner::Destroyed => Err(icu_provider::DataError::custom(
306 "This provider has been destroyed",
307 ))?,
308 $crate::provider::ICU4XDataProviderInner::Empty => $unstable(&icu_provider_adapters::empty::EmptyDataProvider::new(), $($args,)*),
309 #[cfg(feature = "buffer_provider")]
310 $crate::provider::ICU4XDataProviderInner::Buffer(buffer_provider) => $unstable(&icu_provider::AsDeserializingBufferProvider::as_deserializing(buffer_provider), $($args,)*),
311 #[cfg(feature = "compiled_data")]
312 $crate::provider::ICU4XDataProviderInner::Compiled => { let $pre_transform = $compiled($($args,)*); $transform },
313 }
314 };
315 ($compiled:path, $unstable:path, $provider:expr $(, $args:expr)* $(,)?) => {
316 match &$provider.0 {
317 $crate::provider::ICU4XDataProviderInner::Destroyed => Err(icu_provider::DataError::custom(
318 "This provider has been destroyed",
319 ))?,
320 $crate::provider::ICU4XDataProviderInner::Empty => $unstable(&icu_provider_adapters::empty::EmptyDataProvider::new(), $($args,)*),
321 #[cfg(feature = "buffer_provider")]
322 $crate::provider::ICU4XDataProviderInner::Buffer(buffer_provider) => $unstable(&icu_provider::AsDeserializingBufferProvider::as_deserializing(buffer_provider), $($args,)*),
323 #[cfg(feature = "compiled_data")]
324 $crate::provider::ICU4XDataProviderInner::Compiled => $compiled($($args,)*),
325 }
326 };
327}
328
329#[cfg(not(feature = "buffer_provider"))]
330impl<M> DataProvider<M> for ICU4XDataProviderInner
331where
332 M: KeyedDataMarker,
333{
334 load!();
335}
336
337#[cfg(feature = "buffer_provider")]
338impl<M> DataProvider<M> for ICU4XDataProviderInner
339where
340 M: KeyedDataMarker,
341 for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: serde::Deserialize<'de>,
345{
346 load!();
347}