1#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
7
8use crate::size_test_macro::size_test;
9use alloc::borrow::Cow;
10use icu_calendar::types::MonthCode;
11use icu_provider::prelude::*;
12use potential_utf::PotentialUtf8;
13use tinystr::{tinystr, TinyStr4};
14use zerovec::ZeroMap;
15
16size_test!(DateSymbols, date_symbols_v1_size, 3792);
17
18#[doc = date_symbols_v1_size!()]
22#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
29#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
30#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar))]
31#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
32#[yoke(prove_covariance_manually)]
33pub struct DateSymbols<'data> {
34 #[cfg_attr(feature = "serde", serde(borrow))]
36 pub months: months::Contexts<'data>,
37 #[cfg_attr(feature = "serde", serde(borrow))]
39 pub weekdays: weekdays::Contexts<'data>,
40 #[cfg_attr(feature = "serde", serde(borrow))]
42 pub eras: Eras<'data>,
43}
44
45icu_provider::data_struct!(
46 DateSymbols<'_>,
47 #[cfg(feature = "datagen")]
48);
49
50size_test!(TimeSymbols, time_symbols_v1_size, 768);
51
52#[doc = time_symbols_v1_size!()]
56#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
63#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
64#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar))]
65#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
66#[yoke(prove_covariance_manually)]
67pub struct TimeSymbols<'data> {
68 #[cfg_attr(feature = "serde", serde(borrow))]
70 pub day_periods: day_periods::Contexts<'data>,
71}
72
73icu_provider::data_struct!(
74 TimeSymbols<'_>,
75 #[cfg(feature = "datagen")]
76);
77
78#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
95#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
96#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar))]
97#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
98#[yoke(prove_covariance_manually)]
99pub struct Eras<'data> {
100 #[cfg_attr(feature = "serde", serde(borrow))]
104 pub names: ZeroMap<'data, PotentialUtf8, str>,
105 #[cfg_attr(feature = "serde", serde(borrow))]
109 pub abbr: ZeroMap<'data, PotentialUtf8, str>,
110 #[cfg_attr(feature = "serde", serde(borrow))]
114 pub narrow: ZeroMap<'data, PotentialUtf8, str>,
115}
116
117macro_rules! symbols {
120 ($(#[$symbols_attr:meta])* $name: ident, $field_id: ident, $symbols: item) => {
121
122 $(#[$symbols_attr])*
123 #[doc = concat!("Formatting symbols for [`",
124 stringify!($field_id),
125 "`](crate::provider::fields::FieldSymbol::",
126 stringify!($field_id),
127 ").\n\n",
128 "For more information on date time symbols, see [`FieldSymbol`](crate::provider::fields::FieldSymbol).")]
129 pub mod $name {
130 use super::*;
131
132 #[derive(Debug, PartialEq, Clone, zerofrom::ZeroFrom, yoke::Yokeable)]
133 #[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
134 #[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar::$name))]
135 #[cfg_attr(feature = "serde", derive(serde::Deserialize))]
136 #[yoke(prove_covariance_manually)]
137 #[doc = concat!("Locale data for ", stringify!($field_id), " corresponding to the symbols.")]
138 $symbols
145
146 #[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
149 #[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
150 #[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar::$name))]
151 #[cfg_attr(feature = "serde", derive(serde::Deserialize))]
152 #[yoke(prove_covariance_manually)]
153 #[doc = concat!("Symbol data for the \"format\" style formatting of ", stringify!($field_id),
154 ".\n\nThe format style is used in contexts where it is different from the stand-alone form, ex: ",
155 "a case inflected form where the stand-alone form is the nominative case.")]
156 pub struct FormatWidths<'data> {
163 #[doc = concat!("Abbreviated length symbol for \"format\" style symbol for ", stringify!($name), ".")]
164 #[cfg_attr(feature = "serde", serde(borrow))]
165 pub abbreviated: Symbols<'data>,
166 #[doc = concat!("Narrow length symbol for \"format\" style symbol for ", stringify!($name), ".")]
167 #[cfg_attr(feature = "serde", serde(borrow))]
168 pub narrow: Symbols<'data>,
169 #[doc = concat!("Short length symbol for \"format\" style symbol for ", stringify!($name), ", if present.")]
170 #[cfg_attr(feature = "serde", serde(borrow))]
171 pub short: Option<Symbols<'data>>,
172 #[doc = concat!("Wide length symbol for \"format\" style symbol for ", stringify!($name), ".")]
173 #[cfg_attr(feature = "serde", serde(borrow))]
174 pub wide: Symbols<'data>,
175 }
176
177 #[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
179 #[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
180 #[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar::$name))]
181 #[cfg_attr(feature = "serde", derive(serde::Deserialize))]
182 #[yoke(prove_covariance_manually)]
183 #[doc = concat!("Symbol data for the \"stand-alone\" style formatting of ", stringify!($field_id),
184 ".\n\nThe stand-alone style is used in contexts where the field is displayed by itself.")]
185 pub struct StandAloneWidths<'data> {
192 #[doc = concat!("Abbreviated length symbol for \"stand-alone\" style symbol for ", stringify!($name), ".")]
193 #[cfg_attr(feature = "serde", serde(borrow))]
194 pub abbreviated: Option<Symbols<'data>>,
195 #[doc = concat!("Narrow length symbol for \"stand-alone\" style symbol for ", stringify!($name), ".")]
196 #[cfg_attr(feature = "serde", serde(borrow))]
197 pub narrow: Option<Symbols<'data>>,
198 #[doc = concat!("Short length symbol for \"stand-alone\" style symbol for ", stringify!($name), ".")]
199 #[cfg_attr(feature = "serde", serde(borrow))]
200 pub short: Option<Symbols<'data>>,
201 #[doc = concat!("Wide length symbol for \"stand-alone\" style symbol for ", stringify!($name), ".")]
202 #[cfg_attr(feature = "serde", serde(borrow))]
203 pub wide: Option<Symbols<'data>>,
204 }
205
206 #[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
207 #[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
208 #[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::calendar::$name))]
209 #[cfg_attr(feature = "serde", derive(serde::Deserialize))]
210 #[yoke(prove_covariance_manually)]
211 #[doc = concat!("The struct containing the symbol data for ", stringify!($field_id),
212 " that contains the \"format\" style symbol data ([`FormatWidths`]) and \"stand-alone\" style symbol data ([`StandAloneWidths`]).")]
213 pub struct Contexts<'data> {
220 #[cfg_attr(feature = "serde", serde(borrow))]
222 pub format: FormatWidths<'data>,
223 #[cfg_attr(feature = "serde", serde(borrow))]
225 pub stand_alone: Option<StandAloneWidths<'data>>,
226 }
227 }
228 };
229}
230
231symbols!(
232 months,
233 Month,
234 #[allow(clippy::large_enum_variant)]
235 pub enum Symbols<'data> {
236 SolarTwelve(
240 #[cfg_attr(
241 feature = "serde",
242 serde(
243 borrow,
244 deserialize_with = "icu_provider::serde_borrow_de_utils::array_of_cow"
245 )
246 )]
247 [Cow<'data, str>; 12],
248 ),
249 #[cfg_attr(feature = "serde", serde(borrow))]
251 Other(ZeroMap<'data, MonthCode, str>),
252 }
253);
254
255impl months::Symbols<'_> {
256 pub fn get(&self, code: MonthCode) -> Option<&str> {
258 match *self {
259 Self::SolarTwelve(ref arr) => {
260 const CODE_1: TinyStr4 = tinystr!(4, "M01");
263 const CODE_2: TinyStr4 = tinystr!(4, "M02");
264 const CODE_3: TinyStr4 = tinystr!(4, "M03");
265 const CODE_4: TinyStr4 = tinystr!(4, "M04");
266 const CODE_5: TinyStr4 = tinystr!(4, "M05");
267 const CODE_6: TinyStr4 = tinystr!(4, "M06");
268 const CODE_7: TinyStr4 = tinystr!(4, "M07");
269 const CODE_8: TinyStr4 = tinystr!(4, "M08");
270 const CODE_9: TinyStr4 = tinystr!(4, "M09");
271 const CODE_10: TinyStr4 = tinystr!(4, "M10");
272 const CODE_11: TinyStr4 = tinystr!(4, "M11");
273 const CODE_12: TinyStr4 = tinystr!(4, "M12");
274 let idx = match code.0 {
275 CODE_1 => 0,
276 CODE_2 => 1,
277 CODE_3 => 2,
278 CODE_4 => 3,
279 CODE_5 => 4,
280 CODE_6 => 5,
281 CODE_7 => 6,
282 CODE_8 => 7,
283 CODE_9 => 8,
284 CODE_10 => 9,
285 CODE_11 => 10,
286 CODE_12 => 11,
287 _ => return None,
288 };
289 arr.get(idx).map(|x| &**x)
290 }
291 Self::Other(ref map) => map.get(&code),
292 }
293 }
294}
295
296impl Default for months::Symbols<'_> {
297 fn default() -> Self {
298 Self::Other(Default::default())
299 }
300}
301
302symbols!(
303 weekdays,
304 Weekday,
305 #[derive(Default)]
306 pub struct Symbols<'data>(
307 #[cfg_attr(
308 feature = "serde",
309 serde(
310 borrow,
311 deserialize_with = "icu_provider::serde_borrow_de_utils::array_of_cow"
312 )
313 )]
314 pub [Cow<'data, str>; 7],
315 );
316);
317
318symbols!(
319 day_periods,
320 DayPeriod,
321 #[derive(Default)]
322 pub struct Symbols<'data> {
323 #[cfg_attr(feature = "serde", serde(borrow))]
325 pub am: Cow<'data, str>,
326 #[cfg_attr(feature = "serde", serde(borrow))]
328 pub pm: Cow<'data, str>,
329 #[cfg_attr(
330 feature = "serde",
331 serde(
332 borrow,
333 deserialize_with = "icu_provider::serde_borrow_de_utils::option_of_cow"
334 )
335 )]
336 pub noon: Option<Cow<'data, str>>,
338 #[cfg_attr(
339 feature = "serde",
340 serde(
341 borrow,
342 deserialize_with = "icu_provider::serde_borrow_de_utils::option_of_cow"
343 )
344 )]
345 pub midnight: Option<Cow<'data, str>>,
347 }
348);
349
350#[cfg(all(test, feature = "datagen"))]
351mod test {
352 use super::*;
353 use tinystr::tinystr;
354
355 fn serialize_date() -> Vec<u8> {
356 let months = [
357 (&MonthCode(tinystr!(4, "M01")), "January"),
358 (&MonthCode(tinystr!(4, "M02")), "February"),
359 (&MonthCode(tinystr!(4, "M03")), "March"),
360 (&MonthCode(tinystr!(4, "M04")), "April"),
361 (&MonthCode(tinystr!(4, "M05")), "May"),
362 (&MonthCode(tinystr!(4, "M06")), "June"),
363 (&MonthCode(tinystr!(4, "M07")), "July"),
364 (&MonthCode(tinystr!(4, "M08")), "August"),
365 (&MonthCode(tinystr!(4, "M09")), "September"),
366 (&MonthCode(tinystr!(4, "M10")), "October"),
367 (&MonthCode(tinystr!(4, "M11")), "November"),
368 (&MonthCode(tinystr!(4, "M12")), "December"),
369 ];
370 let months = months::Symbols::Other(months.iter().copied().collect());
371
372 let weekdays = weekdays::Symbols([
373 Cow::Borrowed("Monday"),
374 Cow::Borrowed("Tuesday"),
375 Cow::Borrowed("Wednesday"),
376 Cow::Borrowed("Thursday"),
377 Cow::Borrowed("Friday"),
378 Cow::Borrowed("Saturday"),
379 Cow::Borrowed("Sunday"),
380 ]);
381
382 bincode::serialize(&DateSymbols {
383 months: months::Contexts {
384 format: months::FormatWidths {
385 abbreviated: months.clone(),
386 narrow: months.clone(),
387 short: Some(months.clone()),
388 wide: months.clone(),
389 },
390 stand_alone: Some(months::StandAloneWidths {
391 abbreviated: Some(months.clone()),
392 narrow: Some(months.clone()),
393 short: Some(months.clone()),
394 wide: Some(months.clone()),
395 }),
396 },
397 weekdays: weekdays::Contexts {
398 format: weekdays::FormatWidths {
399 abbreviated: weekdays.clone(),
400 narrow: weekdays.clone(),
401 short: Some(weekdays.clone()),
402 wide: weekdays.clone(),
403 },
404 stand_alone: Some(weekdays::StandAloneWidths {
405 abbreviated: Some(weekdays.clone()),
406 narrow: Some(weekdays.clone()),
407 short: Some(weekdays.clone()),
408 wide: Some(weekdays.clone()),
409 }),
410 },
411 eras: Eras {
412 names: ZeroMap::new(),
413 abbr: ZeroMap::new(),
414 narrow: ZeroMap::new(),
415 },
416 })
417 .unwrap()
418 }
419
420 fn serialize_time() -> Vec<u8> {
421 let day_periods = day_periods::Symbols {
422 am: Cow::Borrowed("am"),
423 pm: Cow::Borrowed("pm"),
424 noon: Some(Cow::Borrowed("noon")),
425 midnight: None,
426 };
427
428 bincode::serialize(&TimeSymbols {
429 day_periods: day_periods::Contexts {
430 format: day_periods::FormatWidths {
431 abbreviated: day_periods.clone(),
432 narrow: day_periods.clone(),
433 short: Some(day_periods.clone()),
434 wide: day_periods.clone(),
435 },
436 stand_alone: Some(day_periods::StandAloneWidths {
437 abbreviated: Some(day_periods.clone()),
438 narrow: Some(day_periods.clone()),
439 short: Some(day_periods.clone()),
440 wide: Some(day_periods.clone()),
441 }),
442 },
443 })
444 .unwrap()
445 }
446
447 #[test]
448 fn weekdays_borrows() {
449 let bytes = serialize_date();
450 let de = bincode::deserialize::<DateSymbols>(&bytes).unwrap();
451
452 assert!(matches!(de.weekdays.format.narrow.0[2], Cow::Borrowed(_)));
453 assert!(matches!(
454 de.weekdays.format.short.as_ref().unwrap().0[4],
455 Cow::Borrowed(_)
456 ));
457 }
458
459 #[test]
460 fn day_periods_borrows() {
461 let bytes = serialize_time();
462 let de = bincode::deserialize::<TimeSymbols>(&bytes).unwrap();
463
464 assert!(matches!(
465 de.day_periods.format.narrow.noon,
466 Some(Cow::Borrowed(_))
467 ));
468 assert!(matches!(
469 de.day_periods.format.short.as_ref().unwrap().noon,
470 Some(Cow::Borrowed(_))
471 ));
472
473 assert!(matches!(de.day_periods.format.narrow.am, Cow::Borrowed(_)));
474 assert!(matches!(
475 de.day_periods.format.short.as_ref().unwrap().am,
476 Cow::Borrowed(_)
477 ));
478 }
479}