1use crate::error::ErrorField;
6use crate::pattern::{
7 DayPeriodNameLength, MonthNameLength, PatternLoadError, WeekdayNameLength, YearNameLength,
8};
9use crate::provider::neo::*;
10use crate::provider::time_zones::tz;
11use core::fmt;
12use icu_provider::prelude::*;
13use yoke::Yokeable;
14
15use super::UnstableSealed;
16
17#[allow(missing_docs)]
28pub trait DateTimeNamesMarker: UnstableSealed {
29 type YearNames: NamesContainer<YearNamesV1, YearNameLength>;
30 type MonthNames: NamesContainer<MonthNamesV1, MonthNameLength>;
31 type WeekdayNames: NamesContainer<WeekdayNamesV1, WeekdayNameLength>;
32 type DayPeriodNames: NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>;
33 type ZoneEssentials: NamesContainer<tz::EssentialsV1, ()>;
34 type ZoneLocations: NamesContainer<tz::LocationsOverrideV1, ()>;
35 type ZoneLocationsRoot: NamesContainer<tz::LocationsRootV1, ()>;
36 type ZoneExemplars: NamesContainer<tz::CitiesOverrideV1, ()>;
37 type ZoneExemplarsRoot: NamesContainer<tz::CitiesRootV1, ()>;
38 type ZoneGenericLong: NamesContainer<tz::MzGenericLongV1, ()>;
39 type ZoneGenericShort: NamesContainer<tz::MzGenericShortV1, ()>;
40 type ZoneStandardLong: NamesContainer<tz::MzStandardLongV1, ()>;
41 type ZoneSpecificLong: NamesContainer<tz::MzSpecificLongV1, ()>;
42 type ZoneSpecificShort: NamesContainer<tz::MzSpecificShortV1, ()>;
43 type MetazoneLookup: NamesContainer<tz::MzPeriodV1, ()>;
44}
45
46pub trait MaybeAsErrorField: UnstableSealed {
48 fn maybe_as_error_field(&self) -> Option<ErrorField>;
49}
50
51impl MaybeAsErrorField for () {
52 fn maybe_as_error_field(&self) -> Option<ErrorField> {
53 None
54 }
55}
56
57impl UnstableSealed for YearNameLength {}
58impl MaybeAsErrorField for YearNameLength {
59 fn maybe_as_error_field(&self) -> Option<ErrorField> {
60 Some(self.to_approximate_error_field())
61 }
62}
63
64impl UnstableSealed for MonthNameLength {}
65impl MaybeAsErrorField for MonthNameLength {
66 fn maybe_as_error_field(&self) -> Option<ErrorField> {
67 Some(self.to_approximate_error_field())
68 }
69}
70
71impl UnstableSealed for WeekdayNameLength {}
72impl MaybeAsErrorField for WeekdayNameLength {
73 fn maybe_as_error_field(&self) -> Option<ErrorField> {
74 Some(self.to_approximate_error_field())
75 }
76}
77
78impl UnstableSealed for DayPeriodNameLength {}
79impl MaybeAsErrorField for DayPeriodNameLength {
80 fn maybe_as_error_field(&self) -> Option<ErrorField> {
81 Some(self.to_approximate_error_field())
82 }
83}
84
85#[allow(missing_docs)]
92pub trait NamesContainer<M: DynamicDataMarker, Variables>: UnstableSealed
93where
94 Variables: PartialEq + Copy + fmt::Debug,
95{
96 type Container: MaybePayload<M, Variables> + fmt::Debug + Clone;
97}
98
99impl<M: DynamicDataMarker, Variables> NamesContainer<M, Variables> for ()
100where
101 Variables: PartialEq + Copy + fmt::Debug,
102{
103 type Container = ();
104}
105
106macro_rules! impl_holder_trait {
107 ($marker:path) => {
108 impl UnstableSealed for $marker {}
109 impl<Variables> NamesContainer<$marker, Variables> for $marker
110 where
111 Variables: PartialEq + Copy + MaybeAsErrorField + fmt::Debug,
112 {
113 type Container = DataPayloadWithVariables<$marker, Variables>;
114 }
115 };
116}
117
118impl_holder_trait!(YearNamesV1);
119impl_holder_trait!(MonthNamesV1);
120impl_holder_trait!(WeekdayNamesV1);
121impl_holder_trait!(DayPeriodNamesV1);
122impl_holder_trait!(tz::EssentialsV1);
123impl_holder_trait!(tz::LocationsOverrideV1);
124impl_holder_trait!(tz::LocationsRootV1);
125impl_holder_trait!(tz::CitiesOverrideV1);
126impl_holder_trait!(tz::CitiesRootV1);
127impl_holder_trait!(tz::MzGenericLongV1);
128impl_holder_trait!(tz::MzGenericShortV1);
129impl_holder_trait!(tz::MzStandardLongV1);
130impl_holder_trait!(tz::MzSpecificLongV1);
131impl_holder_trait!(tz::MzSpecificShortV1);
132impl_holder_trait!(tz::MzPeriodV1);
133
134#[allow(missing_docs)]
136#[derive(Debug, Copy, Clone, displaydoc::Display)]
137#[non_exhaustive]
138pub enum MaybePayloadError {
139 FormatterTooSpecific,
141 ConflictingField(ErrorField),
143}
144
145impl core::error::Error for MaybePayloadError {}
146
147impl MaybePayloadError {
148 pub(crate) fn into_load_error(self, error_field: ErrorField) -> PatternLoadError {
149 match self {
150 Self::FormatterTooSpecific => PatternLoadError::FormatterTooSpecific(error_field),
151 Self::ConflictingField(loaded_field) => PatternLoadError::ConflictingField {
152 field: error_field,
153 previous_field: loaded_field,
154 },
155 }
156 }
157}
158
159#[allow(missing_docs)]
169pub trait MaybePayload<M: DynamicDataMarker, Variables>: UnstableSealed {
170 fn new_empty() -> Self;
171 fn load_put<P>(
172 &mut self,
173 provider: &P,
174 req: DataRequest,
175 variables: Variables,
176 ) -> Result<Result<DataResponseMetadata, DataError>, MaybePayloadError>
177 where
178 P: BoundDataProvider<M> + ?Sized,
179 Self: Sized;
180 fn get(&self) -> DataPayloadWithVariablesBorrowed<'_, M, Variables>;
181}
182
183pub struct DataPayloadWithVariables<M: DynamicDataMarker, Variables> {
186 inner: OptionalNames<Variables, DataPayload<M>>,
187}
188
189impl<M: DynamicDataMarker, Variables> Clone for DataPayloadWithVariables<M, Variables>
190where
191 Variables: Clone,
192 DataPayload<M>: Clone,
193{
194 fn clone(&self) -> Self {
195 Self {
196 inner: self.inner.clone(),
197 }
198 }
199}
200
201impl<M: DynamicDataMarker, Variables> UnstableSealed for DataPayloadWithVariables<M, Variables> {}
202
203impl<M: DynamicDataMarker, Variables> fmt::Debug for DataPayloadWithVariables<M, Variables>
204where
205 Variables: fmt::Debug,
206 DataPayload<M>: fmt::Debug,
207{
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 self.inner.fmt(f)
210 }
211}
212
213impl<M: DynamicDataMarker, Variables> From<()> for DataPayloadWithVariables<M, Variables> {
215 #[inline]
216 fn from(_: ()) -> Self {
217 Self {
218 inner: OptionalNames::None,
219 }
220 }
221}
222
223#[allow(missing_docs)]
225pub struct DataPayloadWithVariablesBorrowed<'data, M: DynamicDataMarker, Variables> {
226 pub(crate) inner: OptionalNames<Variables, &'data <M::DataStruct as Yokeable<'data>>::Output>,
227}
228
229impl<'data, M: DynamicDataMarker, Variables> fmt::Debug
230 for DataPayloadWithVariablesBorrowed<'data, M, Variables>
231where
232 <M::DataStruct as Yokeable<'data>>::Output: fmt::Debug,
233 Variables: fmt::Debug,
234{
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 f.debug_struct(core::any::type_name::<Self>())
237 .field("inner", &self.inner)
238 .finish()
239 }
240}
241
242impl<M: DynamicDataMarker, Variables> MaybePayload<M, Variables>
243 for DataPayloadWithVariables<M, Variables>
244where
245 Variables: PartialEq + Copy + MaybeAsErrorField,
246{
247 #[inline]
248 fn new_empty() -> Self {
249 Self {
250 inner: OptionalNames::None,
251 }
252 }
253 fn load_put<P>(
254 &mut self,
255 provider: &P,
256 req: DataRequest,
257 variables: Variables,
258 ) -> Result<Result<DataResponseMetadata, DataError>, MaybePayloadError>
259 where
260 P: BoundDataProvider<M> + ?Sized,
261 Self: Sized,
262 {
263 let arg_variables = variables;
264 match &self.inner {
265 OptionalNames::SingleLength { variables, .. } if arg_variables == *variables => {
266 return Ok(Ok(Default::default()));
268 }
269 OptionalNames::SingleLength { variables, .. } => {
270 let loaded_field = match variables.maybe_as_error_field() {
271 Some(x) => x,
272 None => {
273 debug_assert!(false, "all non-unit variables implement this trait");
274 use crate::provider::fields::*;
275 ErrorField(Field {
276 symbol: FieldSymbol::Era,
277 length: FieldLength::Six,
278 })
279 }
280 };
281 return Err(MaybePayloadError::ConflictingField(loaded_field));
282 }
283 OptionalNames::None => (),
284 };
285 match provider.load_bound(req) {
286 Ok(response) => {
287 self.inner = OptionalNames::SingleLength {
288 payload: response.payload,
289 variables: arg_variables,
290 };
291 Ok(Ok(response.metadata))
292 }
293 Err(e) => Ok(Err(e)),
294 }
295 }
296 #[inline]
297 fn get(&self) -> DataPayloadWithVariablesBorrowed<'_, M, Variables> {
298 DataPayloadWithVariablesBorrowed {
299 inner: self.inner.as_borrowed(),
300 }
301 }
302}
303
304impl<M: DynamicDataMarker, Variables> MaybePayload<M, Variables> for () {
305 #[inline]
306 fn new_empty() -> Self {}
307 #[inline]
308 fn load_put<P>(
309 &mut self,
310 _: &P,
311 _: DataRequest,
312 _: Variables,
313 ) -> Result<Result<DataResponseMetadata, DataError>, MaybePayloadError>
314 where
315 P: BoundDataProvider<M> + ?Sized,
316 Self: Sized,
317 {
318 Err(MaybePayloadError::FormatterTooSpecific)
319 }
320 #[inline]
321 fn get(&self) -> DataPayloadWithVariablesBorrowed<'_, M, Variables> {
322 DataPayloadWithVariablesBorrowed {
323 inner: OptionalNames::None,
324 }
325 }
326}
327
328#[derive(Debug, Copy, Clone)]
331pub(crate) enum OptionalNames<Variables, Payload> {
332 None,
333 SingleLength {
334 variables: Variables,
335 payload: Payload,
336 },
337}
338
339impl<Variables, Payload> OptionalNames<Variables, Payload>
340where
341 Variables: Copy + PartialEq,
342 Payload: Copy,
343{
344 pub(crate) fn get_with_variables(&self, arg_variables: Variables) -> Option<Payload> {
345 match self {
346 Self::None => None,
347 Self::SingleLength { variables, payload } if arg_variables == *variables => {
348 Some(*payload)
349 }
350 _ => None,
351 }
352 }
353}
354
355impl<Payload> OptionalNames<(), Payload>
356where
357 Payload: Copy,
358{
359 pub(crate) fn get_option(&self) -> Option<Payload> {
360 match self {
361 Self::SingleLength {
362 variables: (),
363 payload,
364 } => Some(*payload),
365 _ => None,
366 }
367 }
368}
369
370impl<M: DynamicDataMarker, Variables> OptionalNames<Variables, DataPayload<M>>
371where
372 Variables: Copy,
373{
374 #[inline]
375 pub(crate) fn as_borrowed<'a>(
376 &'a self,
377 ) -> OptionalNames<Variables, &'a <M::DataStruct as Yokeable<'a>>::Output> {
378 match self {
379 Self::None => OptionalNames::None,
380 Self::SingleLength { variables, payload } => OptionalNames::SingleLength {
381 variables: *variables,
382 payload: payload.get(),
383 },
384 }
385 }
386}
387
388#[allow(missing_docs)]
425pub trait DateTimeNamesFrom<M: DateTimeNamesMarker>: DateTimeNamesMarker {
427 fn map_year_names(
428 other: <M::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container,
429 ) -> <Self::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container;
430 fn map_month_names(
431 other: <M::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container,
432 ) -> <Self::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container;
433 fn map_weekday_names(
434 other: <M::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container,
435 ) -> <Self::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container;
436 fn map_day_period_names(
437 other: <M::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container,
438 ) -> <Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container;
439 fn map_zone_essentials(
440 other: <M::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container,
441 ) -> <Self::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container;
442 fn map_zone_locations(
443 other: <M::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container,
444 ) -> <Self::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container;
445 fn map_zone_locations_root(
446 other: <M::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container,
447 ) -> <Self::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container;
448 fn map_zone_exemplars(
449 other: <M::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container,
450 ) -> <Self::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container;
451 fn map_zone_exemplars_root(
452 other: <M::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container,
453 ) -> <Self::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container;
454 fn map_zone_generic_long(
455 other: <M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container,
456 ) -> <Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container;
457 fn map_zone_generic_short(
458 other: <M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container,
459 ) -> <Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container;
460 fn map_zone_standard_long(
461 other: <M::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container,
462 ) -> <Self::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container;
463 fn map_zone_specific_long(
464 other: <M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container,
465 ) -> <Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container;
466 fn map_zone_specific_short(
467 other: <M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container,
468 ) -> <Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container;
469 fn map_metazone_lookup(
470 other: <M::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container,
471 ) -> <Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container;
472}
473
474impl<M: DateTimeNamesMarker, T: DateTimeNamesMarker> DateTimeNamesFrom<M> for T
475where
476 <Self::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container:
477 From<<M::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container>,
478 <Self::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container:
479 From<<M::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container>,
480 <Self::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container:
481 From<<M::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container>,
482 <Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container:
483 From<
484 <M::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container,
485 >,
486 <Self::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container:
487 From<<M::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container>,
488 <Self::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container:
489 From<<M::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container>,
490 <Self::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container:
491 From<<M::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container>,
492 <Self::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container:
493 From<<M::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container>,
494 <Self::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container:
495 From<<M::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container>,
496 <Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container:
497 From<<M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container>,
498 <Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container:
499 From<<M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container>,
500 <Self::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container:
501 From<<M::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container>,
502 <Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container:
503 From<<M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container>,
504 <Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container:
505 From<<M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container>,
506 <Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container:
507 From<<M::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container>,
508{
509 #[inline]
510 fn map_year_names(
511 other: <M::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container,
512 ) -> <Self::YearNames as NamesContainer<YearNamesV1, YearNameLength>>::Container {
513 other.into()
514 }
515 #[inline]
516 fn map_month_names(
517 other: <M::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container,
518 ) -> <Self::MonthNames as NamesContainer<MonthNamesV1, MonthNameLength>>::Container {
519 other.into()
520 }
521 #[inline]
522 fn map_weekday_names(
523 other: <M::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container,
524 ) -> <Self::WeekdayNames as NamesContainer<WeekdayNamesV1, WeekdayNameLength>>::Container {
525 other.into()
526 }
527 #[inline]
528 fn map_day_period_names(
529 other: <M::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container,
530 ) -> <Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1, DayPeriodNameLength>>::Container
531 {
532 other.into()
533 }
534 #[inline]
535 fn map_zone_essentials(
536 other: <M::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container,
537 ) -> <Self::ZoneEssentials as NamesContainer<tz::EssentialsV1, ()>>::Container {
538 other.into()
539 }
540 #[inline]
541 fn map_zone_locations(
542 other: <M::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container,
543 ) -> <Self::ZoneLocations as NamesContainer<tz::LocationsOverrideV1, ()>>::Container {
544 other.into()
545 }
546 #[inline]
547 fn map_zone_locations_root(
548 other: <M::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container,
549 ) -> <Self::ZoneLocationsRoot as NamesContainer<tz::LocationsRootV1, ()>>::Container {
550 other.into()
551 }
552 #[inline]
553 fn map_zone_exemplars(
554 other: <M::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container,
555 ) -> <Self::ZoneExemplars as NamesContainer<tz::CitiesOverrideV1, ()>>::Container {
556 other.into()
557 }
558 #[inline]
559 fn map_zone_exemplars_root(
560 other: <M::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container,
561 ) -> <Self::ZoneExemplarsRoot as NamesContainer<tz::CitiesRootV1, ()>>::Container {
562 other.into()
563 }
564 #[inline]
565 fn map_zone_generic_long(
566 other: <M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container,
567 ) -> <Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1, ()>>::Container {
568 other.into()
569 }
570 #[inline]
571 fn map_zone_generic_short(
572 other: <M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container,
573 ) -> <Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1, ()>>::Container {
574 other.into()
575 }
576 #[inline]
577 fn map_zone_standard_long(
578 other: <M::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container,
579 ) -> <Self::ZoneStandardLong as NamesContainer<tz::MzStandardLongV1, ()>>::Container {
580 other.into()
581 }
582 #[inline]
583 fn map_zone_specific_long(
584 other: <M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container,
585 ) -> <Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1, ()>>::Container {
586 other.into()
587 }
588 #[inline]
589 fn map_zone_specific_short(
590 other: <M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container,
591 ) -> <Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1, ()>>::Container {
592 other.into()
593 }
594 #[inline]
595 fn map_metazone_lookup(
596 other: <M::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container,
597 ) -> <Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1, ()>>::Container {
598 other.into()
599 }
600}