time_macros/format_description/public/
optimizing.rs1use std::mem;
12
13use super::{Component, OwnedFormatItem, OwnedFormatItemInner};
14
15impl OwnedFormatItem {
16 pub(crate) fn optimize(&mut self) {
17 self.inner.optimize();
18 }
19}
20
21impl OwnedFormatItemInner {
22 pub(crate) fn optimize(&mut self) {
23 match self {
25 Self::Literal(_) | Self::StringLiteral(_) | Self::Component(_) => {}
26 Self::Compound(items) | Self::First(items) => {
27 for item in items {
28 item.optimize();
29 }
30 }
31 Self::Optional { format: _, item } => item.optimize(),
32 }
33
34 let passes = [
39 Self::only_formatting_uplift_optional,
41 Self::only_formatting_uplift_first,
42 Self::only_formatting_eliminate_end,
43 Self::unnest_nested_compounds,
45 Self::unnest_nested_first,
46 Self::compound_containing_empty_string,
47 Self::merge_consecutive_literals,
49 Self::unnest_trivial_compounds,
50 Self::unnest_first_only_one,
51 ];
52 for pass in passes {
53 pass(self);
54 }
55 }
56
57 const fn no_op() -> Self {
58 Self::StringLiteral(String::new())
59 }
60
61 fn merge_consecutive_literals(&mut self) -> bool {
66 let Self::Compound(items) = self else {
67 return false;
68 };
69
70 let mut something_was_changed = false;
71 let mut idx = 1;
72 while idx < items.len() {
73 let pair = unsafe { items.get_disjoint_unchecked_mut([idx - 1, idx]) };
75
76 match pair {
77 [Self::Literal(a), Self::Literal(b)] => {
78 a.append(b);
79 items.remove(idx);
80 something_was_changed = true;
81 }
82 [Self::Literal(a), Self::StringLiteral(b)] => {
83 a.extend(b.as_bytes());
84 items.remove(idx);
85 something_was_changed = true;
86 }
87 [item @ Self::StringLiteral(_), Self::Literal(b)] => {
88 let Self::StringLiteral(a) = item else {
89 unreachable!()
90 };
91 let mut bytes = a.as_bytes().to_vec();
92 bytes.append(b);
93 *item = Self::Literal(bytes);
94 items.remove(idx);
95 something_was_changed = true;
96 }
97 [Self::StringLiteral(a), Self::StringLiteral(b)] => {
98 a.push_str(b);
99 items.remove(idx);
100 something_was_changed = true;
101 }
102 _ => idx += 1,
103 }
104 }
105
106 something_was_changed
107 }
108
109 fn unnest_trivial_compounds(&mut self) -> bool {
111 if let Self::Compound(items) = self
112 && items.len() == 1
113 && let Some(item) = items.pop()
114 {
115 *self = item;
116 true
117 } else {
118 false
119 }
120 }
121
122 fn unnest_nested_compounds(&mut self) -> bool {
125 let Self::Compound(items) = self else {
126 return false;
127 };
128
129 let mut idx = 0;
130 let mut something_was_changed = false;
131 while idx < items.len() {
132 if let Self::Compound(inner_items) = &mut items[idx] {
133 let inner_items = mem::take(inner_items);
134 items.splice(idx..=idx, inner_items).for_each(drop);
135 something_was_changed = true;
136 } else {
137 idx += 1;
138 }
139 }
140
141 something_was_changed
142 }
143
144 fn unnest_first_only_one(&mut self) -> bool {
146 if let Self::First(items) = self
147 && items.len() == 1
148 && let Some(item) = items.pop()
149 {
150 *self = item;
151 true
152 } else {
153 false
154 }
155 }
156
157 fn unnest_nested_first(&mut self) -> bool {
159 let Self::First(items) = self else {
160 return false;
161 };
162
163 let mut idx = 0;
164 let mut something_was_changed = false;
165 while idx < items.len() {
166 if let Self::First(inner_items) = &mut items[idx] {
167 let inner_items = mem::take(inner_items);
168 items.splice(idx..=idx, inner_items).for_each(drop);
169 something_was_changed = true;
170 } else {
171 idx += 1;
172 }
173 }
174
175 something_was_changed
176 }
177
178 fn only_formatting_uplift_optional(&mut self) -> bool {
183 if !cfg!(feature = "formatting") || cfg!(feature = "parsing") {
186 return false;
187 }
188
189 let Self::Optional { format, item } = self else {
190 return false;
191 };
192
193 let item = if *format {
194 mem::replace(item.as_mut(), Self::no_op())
195 } else {
196 Self::no_op()
197 };
198
199 *self = item;
200 true
201 }
202
203 fn only_formatting_uplift_first(&mut self) -> bool {
207 if !cfg!(feature = "formatting") || cfg!(feature = "parsing") {
210 return false;
211 }
212
213 let Self::First(items) = self else {
214 return false;
215 };
216
217 *self = items.remove(0);
218 true
219 }
220
221 fn only_formatting_eliminate_end(&mut self) -> bool {
222 if !cfg!(feature = "formatting") || cfg!(feature = "parsing") {
225 return false;
226 }
227
228 if let Self::Component(Component::End(_)) = self {
229 *self = Self::no_op();
230 true
231 } else {
232 false
233 }
234 }
235
236 fn compound_containing_empty_string(&mut self) -> bool {
239 let Self::Compound(items) = self else {
240 return false;
241 };
242
243 let mut idx = 0;
244 let mut something_was_changed = false;
245 while idx < items.len() {
246 if let Self::StringLiteral(s) = &items[idx]
247 && s.is_empty()
248 {
249 items.remove(idx);
250 something_was_changed = true;
251 } else {
252 idx += 1;
253 }
254 }
255
256 something_was_changed
257 }
258}