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