1#![allow(clippy::exhaustive_structs)] use crate as icu_provider;
10
11use crate::prelude::*;
12use alloc::borrow::Cow;
13use alloc::collections::BTreeSet;
14use alloc::string::String;
15use core::fmt::Debug;
16use icu_locale_core::preferences::define_preferences;
17use writeable::Writeable;
18use yoke::*;
19use zerofrom::*;
20
21#[derive(Debug, PartialEq, Clone, Yokeable, ZeroFrom)]
23#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
24#[cfg_attr(
25    any(feature = "deserialize_json", feature = "export"),
26    derive(serde::Serialize)
27)]
28#[cfg_attr(feature = "export", derive(databake::Bake))]
29#[cfg_attr(feature = "export", databake(path = icu_provider::hello_world))]
30pub struct HelloWorld<'data> {
31    #[cfg_attr(feature = "serde", serde(borrow))]
33    pub message: Cow<'data, str>,
34}
35
36impl Default for HelloWorld<'_> {
37    fn default() -> Self {
38        HelloWorld {
39            message: Cow::Borrowed("(und) Hello World"),
40        }
41    }
42}
43
44impl<'a> ZeroFrom<'a, str> for HelloWorld<'a> {
45    fn zero_from(message: &'a str) -> Self {
46        HelloWorld {
47            message: Cow::Borrowed(message),
48        }
49    }
50}
51
52crate::data_struct!(
53    HelloWorld<'data>,
54    varule: str,
55    #[cfg(feature = "export")]
56    encode_as_varule: |v: &HelloWorld<'_>| &*v.message
57);
58
59data_marker!(
60    #[derive(Debug)]
62    HelloWorldV1,
63    HelloWorld<'static>,
64    has_checksum = true,
65);
66
67#[derive(Debug, PartialEq, Default)]
108pub struct HelloWorldProvider;
109
110impl HelloWorldProvider {
111    const DATA: &'static [(&'static str, &'static str, &'static str)] = &[
114        ("bn", "", "ওহে বিশ্ব"),
115        ("cs", "", "Ahoj světe"),
116        ("de", "", "Hallo Welt"),
117        ("de-AT", "", "Servus Welt"),
118        ("el", "", "Καλημέρα κόσμε"),
119        ("en", "", "Hello World"),
120        ("en-001", "", "Hello from 🗺️"),
122        ("en-002", "", "Hello from 🌍"),
124        ("en-019", "", "Hello from 🌎"),
126        ("en-142", "", "Hello from 🌏"),
128        ("en-GB", "", "Hello from 🇬🇧"),
130        ("en-GB-u-sd-gbeng", "", "Hello from 🏴"),
132        ("en", "reverse", "Olleh Dlrow"),
133        ("eo", "", "Saluton, Mondo"),
134        ("fa", "", "سلام دنیا"),
135        ("fi", "", "hei maailma"),
136        ("is", "", "Halló, heimur"),
137        ("ja", "", "こんにちは世界"),
138        ("ja", "reverse", "界世はちにんこ"),
139        ("la", "", "Ave, munde"),
140        ("pt", "", "Olá, mundo"),
141        ("ro", "", "Salut, lume"),
142        ("ru", "", "Привет, мир"),
143        ("sr", "", "Поздрав свете"),
144        ("sr-Latn", "", "Pozdrav svete"),
145        ("vi", "", "Xin chào thế giới"),
146        ("zh", "", "你好世界"),
147    ];
148
149    #[cfg(feature = "deserialize_json")]
151    pub fn into_json_provider(self) -> HelloWorldJsonProvider {
152        HelloWorldJsonProvider
153    }
154}
155
156impl DataProvider<HelloWorldV1> for HelloWorldProvider {
157    fn load(&self, req: DataRequest) -> Result<DataResponse<HelloWorldV1>, DataError> {
158        #[allow(clippy::indexing_slicing)] let data = Self::DATA
160            .iter()
161            .find(|(l, a, _)| {
162                req.id.locale.strict_cmp(l.as_bytes()).is_eq()
163                    && *a == req.id.marker_attributes.as_str()
164            })
165            .map(|(_, _, v)| v)
166            .ok_or_else(|| DataErrorKind::IdentifierNotFound.with_req(HelloWorldV1::INFO, req))?;
167        Ok(DataResponse {
168            metadata: DataResponseMetadata::default().with_checksum(1234),
169            payload: DataPayload::from_static_str(data),
170        })
171    }
172}
173
174impl DryDataProvider<HelloWorldV1> for HelloWorldProvider {
175    fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
176        self.load(req).map(|r| r.metadata)
177    }
178}
179
180impl DataPayload<HelloWorldV1> {
181    pub fn from_static_str(s: &'static str) -> DataPayload<HelloWorldV1> {
183        DataPayload::from_owned(HelloWorld {
184            message: Cow::Borrowed(s),
185        })
186    }
187}
188
189#[cfg(feature = "deserialize_json")]
190#[derive(Debug)]
211pub struct HelloWorldJsonProvider;
212
213#[cfg(feature = "deserialize_json")]
214impl DynamicDataProvider<BufferMarker> for HelloWorldJsonProvider {
215    fn load_data(
216        &self,
217        marker: DataMarkerInfo,
218        req: DataRequest,
219    ) -> Result<DataResponse<BufferMarker>, DataError> {
220        marker.match_marker(HelloWorldV1::INFO)?;
221        let result = HelloWorldProvider.load(req)?;
222        Ok(DataResponse {
223            metadata: DataResponseMetadata {
224                buffer_format: Some(icu_provider::buf::BufferFormat::Json),
225                ..result.metadata
226            },
227            #[allow(clippy::unwrap_used)] payload: DataPayload::from_owned_buffer(
229                serde_json::to_string(result.payload.get())
230                    .unwrap()
231                    .into_bytes()
232                    .into_boxed_slice(),
233            ),
234        })
235    }
236}
237
238impl IterableDataProvider<HelloWorldV1> for HelloWorldProvider {
239    fn iter_ids(&self) -> Result<BTreeSet<DataIdentifierCow>, DataError> {
240        #[allow(clippy::unwrap_used)] Ok(Self::DATA
242            .iter()
243            .map(|(l, a, _)| {
244                DataIdentifierCow::from_borrowed_and_owned(
245                    DataMarkerAttributes::from_str_or_panic(a),
246                    l.parse().unwrap(),
247                )
248            })
249            .collect())
250    }
251}
252
253#[cfg(feature = "export")]
254icu_provider::export::make_exportable_provider!(HelloWorldProvider, [HelloWorldV1,]);
255
256define_preferences!(
257    [Copy]
259    HelloWorldFormatterPreferences, {}
260);
261
262#[derive(Debug)]
282pub struct HelloWorldFormatter {
283    data: DataPayload<HelloWorldV1>,
284}
285
286#[derive(Debug)]
290pub struct FormattedHelloWorld<'l> {
291    data: &'l HelloWorld<'l>,
292}
293
294impl HelloWorldFormatter {
295    pub fn try_new(prefs: HelloWorldFormatterPreferences) -> Result<Self, DataError> {
299        Self::try_new_unstable(&HelloWorldProvider, prefs)
300    }
301
302    icu_provider::gen_buffer_data_constructors!((prefs: HelloWorldFormatterPreferences) -> error: DataError,
303        functions: [
304            try_new: skip,
305            try_new_with_buffer_provider,
306            try_new_unstable,
307            Self,
308    ]);
309
310    #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
311    pub fn try_new_unstable<P>(
312        provider: &P,
313        prefs: HelloWorldFormatterPreferences,
314    ) -> Result<Self, DataError>
315    where
316        P: DataProvider<HelloWorldV1>,
317    {
318        let locale = HelloWorldV1::make_locale(prefs.locale_preferences);
319        let data = provider
320            .load(DataRequest {
321                id: crate::request::DataIdentifierBorrowed::for_locale(&locale),
322                ..Default::default()
323            })?
324            .payload;
325        Ok(Self { data })
326    }
327
328    #[allow(clippy::needless_lifetimes)] pub fn format<'l>(&'l self) -> FormattedHelloWorld<'l> {
331        FormattedHelloWorld {
332            data: self.data.get(),
333        }
334    }
335
336    pub fn format_to_string(&self) -> String {
338        self.format().write_to_string().into_owned()
339    }
340}
341
342impl Writeable for FormattedHelloWorld<'_> {
343    fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
344        self.data.message.write_to(sink)
345    }
346
347    fn write_to_string(&self) -> Cow<str> {
348        self.data.message.clone()
349    }
350
351    fn writeable_length_hint(&self) -> writeable::LengthHint {
352        self.data.message.writeable_length_hint()
353    }
354}
355
356writeable::impl_display_with_writeable!(FormattedHelloWorld<'_>);
357
358#[cfg(feature = "export")]
359#[test]
360fn test_iter() {
361    use crate::IterableDataProvider;
362    use icu_locale_core::locale;
363
364    assert_eq!(
365        HelloWorldProvider.iter_ids().unwrap(),
366        BTreeSet::from_iter([
367            DataIdentifierCow::from_locale(locale!("bn").into()),
368            DataIdentifierCow::from_locale(locale!("cs").into()),
369            DataIdentifierCow::from_locale(locale!("de").into()),
370            DataIdentifierCow::from_locale(locale!("de-AT").into()),
371            DataIdentifierCow::from_locale(locale!("el").into()),
372            DataIdentifierCow::from_locale(locale!("en").into()),
373            DataIdentifierCow::from_locale(locale!("en-001").into()),
374            DataIdentifierCow::from_locale(locale!("en-002").into()),
375            DataIdentifierCow::from_locale(locale!("en-019").into()),
376            DataIdentifierCow::from_locale(locale!("en-142").into()),
377            DataIdentifierCow::from_locale(locale!("en-GB").into()),
378            DataIdentifierCow::from_locale(locale!("en-GB-u-sd-gbeng").into()),
379            DataIdentifierCow::from_borrowed_and_owned(
380                DataMarkerAttributes::from_str_or_panic("reverse"),
381                locale!("en").into()
382            ),
383            DataIdentifierCow::from_locale(locale!("eo").into()),
384            DataIdentifierCow::from_locale(locale!("fa").into()),
385            DataIdentifierCow::from_locale(locale!("fi").into()),
386            DataIdentifierCow::from_locale(locale!("is").into()),
387            DataIdentifierCow::from_locale(locale!("ja").into()),
388            DataIdentifierCow::from_borrowed_and_owned(
389                DataMarkerAttributes::from_str_or_panic("reverse"),
390                locale!("ja").into()
391            ),
392            DataIdentifierCow::from_locale(locale!("la").into()),
393            DataIdentifierCow::from_locale(locale!("pt").into()),
394            DataIdentifierCow::from_locale(locale!("ro").into()),
395            DataIdentifierCow::from_locale(locale!("ru").into()),
396            DataIdentifierCow::from_locale(locale!("sr").into()),
397            DataIdentifierCow::from_locale(locale!("sr-Latn").into()),
398            DataIdentifierCow::from_locale(locale!("vi").into()),
399            DataIdentifierCow::from_locale(locale!("zh").into()),
400        ])
401    );
402}