icu_datetime/provider/pattern/runtime/
generic.rs
1use super::{
6 super::{reference, PatternError},
7 super::{GenericPatternItem, PatternItem},
8 Pattern,
9};
10use alloc::vec::Vec;
11use core::str::FromStr;
12use icu_provider::prelude::*;
13use zerovec::ZeroVec;
14
15#[derive(Debug, PartialEq, Eq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
27#[allow(clippy::exhaustive_structs)] #[cfg_attr(feature = "datagen", derive(databake::Bake))]
29#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern::runtime))]
30pub struct GenericPattern<'data> {
31 pub items: ZeroVec<'data, GenericPatternItem>,
33}
34
35pub(crate) const ZERO_ONE_TWO_SLICE: &zerovec::ZeroSlice<GenericPatternItem> = zerovec::zeroslice!(
37 GenericPatternItem;
38 GenericPatternItem::to_unaligned_const;
39 [
40 GenericPatternItem::Placeholder(0),
41 GenericPatternItem::Placeholder(1),
42 GenericPatternItem::Placeholder(2),
43 ]
44);
45
46impl<'data> GenericPattern<'data> {
47 pub fn combined(
69 self,
70 date: Pattern<'data>,
71 time: Pattern<'data>,
72 ) -> Result<Pattern<'static>, PatternError> {
73 let size = date.items.len() + time.items.len();
74 let mut result = Vec::with_capacity(self.items.len() + size);
75
76 for item in self.items.iter() {
77 match item {
78 GenericPatternItem::Placeholder(0) => {
79 result.extend(time.items.iter());
80 }
81 GenericPatternItem::Placeholder(1) => {
82 result.extend(date.items.iter());
83 }
84 GenericPatternItem::Placeholder(idx) => {
85 #[allow(clippy::unwrap_used)] return Err(PatternError::UnknownSubstitution(
87 char::from_digit(idx as u32, 10).unwrap(),
88 ));
89 }
90 GenericPatternItem::Literal(ch) => result.push(PatternItem::Literal(ch)),
91 }
92 }
93
94 Ok(Pattern::from(result))
95 }
96}
97
98impl Default for GenericPattern<'_> {
99 fn default() -> Self {
100 Self {
101 items: ZeroVec::new(),
102 }
103 }
104}
105
106impl From<&reference::GenericPattern> for GenericPattern<'_> {
107 fn from(input: &reference::GenericPattern) -> Self {
108 Self {
109 items: ZeroVec::alloc_from_slice(&input.items),
110 }
111 }
112}
113
114impl From<&GenericPattern<'_>> for reference::GenericPattern {
115 fn from(input: &GenericPattern<'_>) -> Self {
116 Self {
117 items: input.items.to_vec(),
118 }
119 }
120}
121
122impl FromStr for GenericPattern<'_> {
123 type Err = PatternError;
124
125 fn from_str(s: &str) -> Result<Self, Self::Err> {
126 let reference = reference::GenericPattern::from_str(s)?;
127 Ok(Self::from(&reference))
128 }
129}
130
131#[cfg(test)]
132#[cfg(feature = "datagen")]
133mod test {
134 use super::*;
135
136 #[test]
137 fn test_runtime_generic_pattern_combine() {
138 let pattern: GenericPattern = "{1} 'at' {0}"
139 .parse()
140 .expect("Failed to parse a generic pattern.");
141
142 let date = "y/M/d".parse().expect("Failed to parse a date pattern.");
143
144 let time = "HH:mm".parse().expect("Failed to parse a time pattern.");
145
146 let pattern = pattern
147 .combined(date, time)
148 .expect("Failed to combine date and time.");
149
150 assert_eq!(pattern.to_string(), "y/M/d 'at' HH:mm");
151 }
152}