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 let data = Self::DATA
159 .iter()
160 .find(|(l, a, _)| {
161 req.id.locale.strict_cmp(l.as_bytes()).is_eq()
162 && *a == req.id.marker_attributes.as_str()
163 })
164 .map(|(_, _, v)| v)
165 .ok_or_else(|| DataErrorKind::IdentifierNotFound.with_req(HelloWorldV1::INFO, req))?;
166 Ok(DataResponse {
167 metadata: DataResponseMetadata::default().with_checksum(1234),
168 payload: DataPayload::from_static_str(data),
169 })
170 }
171}
172
173impl DryDataProvider<HelloWorldV1> for HelloWorldProvider {
174 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
175 self.load(req).map(|r| r.metadata)
176 }
177}
178
179impl DataPayload<HelloWorldV1> {
180 pub fn from_static_str(s: &'static str) -> DataPayload<HelloWorldV1> {
182 DataPayload::from_owned(HelloWorld {
183 message: Cow::Borrowed(s),
184 })
185 }
186}
187
188#[cfg(feature = "deserialize_json")]
189#[derive(Debug)]
210pub struct HelloWorldJsonProvider;
211
212#[cfg(feature = "deserialize_json")]
213impl DynamicDataProvider<BufferMarker> for HelloWorldJsonProvider {
214 fn load_data(
215 &self,
216 marker: DataMarkerInfo,
217 req: DataRequest,
218 ) -> Result<DataResponse<BufferMarker>, DataError> {
219 marker.match_marker(HelloWorldV1::INFO)?;
220 let result = HelloWorldProvider.load(req)?;
221 Ok(DataResponse {
222 metadata: DataResponseMetadata {
223 buffer_format: Some(icu_provider::buf::BufferFormat::Json),
224 ..result.metadata
225 },
226 #[expect(clippy::unwrap_used)] payload: DataPayload::from_owned_buffer(
228 serde_json::to_string(result.payload.get())
229 .unwrap()
230 .into_bytes()
231 .into_boxed_slice(),
232 ),
233 })
234 }
235}
236
237impl IterableDataProvider<HelloWorldV1> for HelloWorldProvider {
238 fn iter_ids(&self) -> Result<BTreeSet<DataIdentifierCow<'_>>, DataError> {
239 #[expect(clippy::unwrap_used)] Ok(Self::DATA
241 .iter()
242 .map(|(l, a, _)| {
243 DataIdentifierCow::from_borrowed_and_owned(
244 DataMarkerAttributes::from_str_or_panic(a),
245 l.parse().unwrap(),
246 )
247 })
248 .collect())
249 }
250}
251
252#[cfg(feature = "export")]
253icu_provider::export::make_exportable_provider!(HelloWorldProvider, [HelloWorldV1,]);
254
255define_preferences!(
256 [Copy]
258 HelloWorldFormatterPreferences, {}
259);
260
261#[derive(Debug)]
281pub struct HelloWorldFormatter {
282 data: DataPayload<HelloWorldV1>,
283}
284
285#[derive(Debug)]
289pub struct FormattedHelloWorld<'l> {
290 data: &'l HelloWorld<'l>,
291}
292
293impl HelloWorldFormatter {
294 pub fn try_new(prefs: HelloWorldFormatterPreferences) -> Result<Self, DataError> {
298 Self::try_new_unstable(&HelloWorldProvider, prefs)
299 }
300
301 icu_provider::gen_buffer_data_constructors!((prefs: HelloWorldFormatterPreferences) -> error: DataError,
302 functions: [
303 try_new: skip,
304 try_new_with_buffer_provider,
305 try_new_unstable,
306 Self,
307 ]);
308
309 #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
310 pub fn try_new_unstable<P>(
311 provider: &P,
312 prefs: HelloWorldFormatterPreferences,
313 ) -> Result<Self, DataError>
314 where
315 P: DataProvider<HelloWorldV1>,
316 {
317 let locale = HelloWorldV1::make_locale(prefs.locale_preferences);
318 let data = provider
319 .load(DataRequest {
320 id: crate::request::DataIdentifierBorrowed::for_locale(&locale),
321 ..Default::default()
322 })?
323 .payload;
324 Ok(Self { data })
325 }
326
327 pub fn format<'l>(&'l self) -> FormattedHelloWorld<'l> {
329 FormattedHelloWorld {
330 data: self.data.get(),
331 }
332 }
333
334 pub fn format_to_string(&self) -> String {
336 self.format().write_to_string().into_owned()
337 }
338}
339
340impl Writeable for FormattedHelloWorld<'_> {
341 fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
342 self.data.message.write_to(sink)
343 }
344
345 fn writeable_borrow(&self) -> Option<&str> {
346 self.data.message.writeable_borrow()
347 }
348
349 fn writeable_length_hint(&self) -> writeable::LengthHint {
350 self.data.message.writeable_length_hint()
351 }
352}
353
354writeable::impl_display_with_writeable!(FormattedHelloWorld<'_>);
355
356#[cfg(feature = "export")]
357#[test]
358fn test_iter() {
359 use crate::IterableDataProvider;
360 use icu_locale_core::locale;
361
362 assert_eq!(
363 HelloWorldProvider.iter_ids().unwrap(),
364 BTreeSet::from_iter([
365 DataIdentifierCow::from_locale(locale!("bn").into()),
366 DataIdentifierCow::from_locale(locale!("cs").into()),
367 DataIdentifierCow::from_locale(locale!("de").into()),
368 DataIdentifierCow::from_locale(locale!("de-AT").into()),
369 DataIdentifierCow::from_locale(locale!("el").into()),
370 DataIdentifierCow::from_locale(locale!("en").into()),
371 DataIdentifierCow::from_locale(locale!("en-001").into()),
372 DataIdentifierCow::from_locale(locale!("en-002").into()),
373 DataIdentifierCow::from_locale(locale!("en-019").into()),
374 DataIdentifierCow::from_locale(locale!("en-142").into()),
375 DataIdentifierCow::from_locale(locale!("en-GB").into()),
376 DataIdentifierCow::from_locale(locale!("en-GB-u-sd-gbeng").into()),
377 DataIdentifierCow::from_borrowed_and_owned(
378 DataMarkerAttributes::from_str_or_panic("reverse"),
379 locale!("en").into()
380 ),
381 DataIdentifierCow::from_locale(locale!("eo").into()),
382 DataIdentifierCow::from_locale(locale!("fa").into()),
383 DataIdentifierCow::from_locale(locale!("fi").into()),
384 DataIdentifierCow::from_locale(locale!("is").into()),
385 DataIdentifierCow::from_locale(locale!("ja").into()),
386 DataIdentifierCow::from_borrowed_and_owned(
387 DataMarkerAttributes::from_str_or_panic("reverse"),
388 locale!("ja").into()
389 ),
390 DataIdentifierCow::from_locale(locale!("la").into()),
391 DataIdentifierCow::from_locale(locale!("pt").into()),
392 DataIdentifierCow::from_locale(locale!("ro").into()),
393 DataIdentifierCow::from_locale(locale!("ru").into()),
394 DataIdentifierCow::from_locale(locale!("sr").into()),
395 DataIdentifierCow::from_locale(locale!("sr-Latn").into()),
396 DataIdentifierCow::from_locale(locale!("vi").into()),
397 DataIdentifierCow::from_locale(locale!("zh").into()),
398 ])
399 );
400}