Skip to content

Commit a9b2b57

Browse files
committed
Pack FixedTimespan into one i32
1 parent 8c919a6 commit a9b2b57

File tree

4 files changed

+36906
-36693
lines changed

4 files changed

+36906
-36693
lines changed

chrono-tz-build/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ parse-zoneinfo = { path = "../parse-zoneinfo", version = "0.5.0" }
2121
regex = { default-features = false, version = "1", optional = true }
2222
phf_codegen = { version = "0.12", default-features = false }
2323
uncased = { version = "0.9", optional = true, default-features = false }
24+
trie-rs = "0.4.2"
2425

2526
# needed only to forward feature for uncased
2627
phf_shared = { version = "0.12", default-features = false, optional = true }

chrono-tz-build/src/lib.rs

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn strip_comments(mut line: String) -> String {
3232

3333
// Generate a list of the time zone periods beyond the first that apply
3434
// to this zone, as a string representation of a static slice.
35-
fn format_rest(rest: Vec<(i64, FixedTimespan)>) -> String {
35+
fn format_rest(rest: Vec<(i64, FixedTimespan)>, strs: &str) -> String {
3636
let mut ret = "&[\n".to_string();
3737
for (
3838
start,
@@ -44,10 +44,10 @@ fn format_rest(rest: Vec<(i64, FixedTimespan)>) -> String {
4444
) in rest
4545
{
4646
ret.push_str(&format!(
47-
" ({start}, FixedTimespan {{ \
48-
offset: {offset}, name: {name:?} \
49-
}}),\n",
47+
" ({start}, FixedTimespan::from_offset_and_name_indices({offset}, {name_idx}, {name_len})),\n",
5048
offset = utc_offset + dst_offset,
49+
name_idx = strs.find(&name).unwrap(),
50+
name_len = name.len(),
5151
));
5252
}
5353
ret.push_str(" ]");
@@ -209,6 +209,50 @@ impl FromStr for Tz {{
209209
}}
210210
}}\n"
211211
)?;
212+
213+
let names_trie = zones
214+
.iter()
215+
.filter_map(|z| table.timespans(z))
216+
.flat_map(|ts| ts.rest.into_iter().map(|t| t.1.name).chain([ts.first.name]))
217+
.collect::<trie_rs::Trie<_>>();
218+
219+
let names_reverse_trie = zones
220+
.iter()
221+
.filter_map(|z| table.timespans(z))
222+
.flat_map(|ts| {
223+
ts.rest
224+
.into_iter()
225+
.map(|t| t.1.name)
226+
.chain([ts.first.name])
227+
.map(|x| x.chars().rev().collect::<String>())
228+
})
229+
.collect::<trie_rs::Trie<_>>();
230+
231+
let strs = names_trie
232+
.iter()
233+
.filter(|x: &String| {
234+
// Any string that is not a prefix or a suffix (prefix in inverse trie) of another string.
235+
// Solving this optimally is NP-complete (shortest common superstring), and even implementing
236+
// an approximate solution to that problem is probably not worth it.
237+
!names_trie.is_prefix(x)
238+
&& !names_reverse_trie.is_prefix(x.chars().rev().collect::<String>())
239+
})
240+
.collect::<Vec<_>>();
241+
242+
writeln!(
243+
timezone_file,
244+
"pub(crate) const COMPACT_NAMES: &str = concat!("
245+
)?;
246+
for s in &strs {
247+
writeln!(timezone_file, " {s:?},")?;
248+
}
249+
writeln!(timezone_file, ");\n")?;
250+
251+
let strs = strs.into_iter().fold(String::new(), |mut s, x| {
252+
s.push_str(&x);
253+
s
254+
});
255+
212256
writeln!(
213257
timezone_file,
214258
"impl TimeSpans for Tz {{
@@ -223,13 +267,14 @@ impl FromStr for Tz {{
223267
writeln!(
224268
timezone_file,
225269
" const {zone}: FixedTimespanSet = FixedTimespanSet {{
226-
first: FixedTimespan {{ offset: {offset}, name: {name:?} }},
270+
first: FixedTimespan::from_offset_and_name_indices({offset}, {name_idx}, {name_len}),
227271
rest: {rest},
228272
}};\n",
229273
zone = zone_name.to_uppercase(),
230-
rest = format_rest(timespans.rest),
274+
rest = format_rest(timespans.rest, &strs),
231275
offset = timespans.first.utc_offset + timespans.first.dst_offset,
232-
name = timespans.first.name,
276+
name_idx = strs.find(&timespans.first.name).unwrap(),
277+
name_len = timespans.first.name.len(),
233278
)?;
234279
}
235280

0 commit comments

Comments
 (0)