@@ -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