1
1
use databake:: { quote, Bake } ;
2
2
use std:: {
3
+ collections:: { BTreeMap , BTreeSet , HashMap } ,
3
4
fs:: { self , File } ,
5
+ hash:: { DefaultHasher , Hash , Hasher } ,
4
6
io:: { self , BufWriter , Write } ,
5
7
path:: Path ,
6
8
} ;
7
- use temporal_provider:: { tzif:: ZoneInfoProvider , IanaIdentifierNormalizer } ;
9
+ use temporal_provider:: {
10
+ tzif:: { ZeroTzifULE , ZoneInfoProvider } ,
11
+ IanaIdentifierNormalizer ,
12
+ } ;
8
13
9
14
trait BakedDataProvider {
10
15
fn write_data ( & self , data_path : & Path ) -> io:: Result < ( ) > ;
@@ -20,7 +25,7 @@ impl BakedDataProvider for ZoneInfoProvider<'_> {
20
25
21
26
let baked_macro = quote ! {
22
27
#[ macro_export]
23
- macro_rules! zone_info_provider {
28
+ macro_rules! zone_info_provider_baked {
24
29
( ) => {
25
30
pub const ZONE_INFO_PROVIDER : & ' static temporal_provider:: ZoneInfoProvider = & #baked;
26
31
}
@@ -41,26 +46,57 @@ impl BakedDataProvider for ZoneInfoProvider<'_> {
41
46
// Recreate directory.
42
47
fs:: create_dir_all ( zoneinfo_debug_path. clone ( ) ) ?;
43
48
49
+ let map_file = zoneinfo_debug_path. join ( "map.json" ) ;
50
+
51
+ // Create id sets for the tzifs
52
+ let mut tzif_ids: HashMap < usize , BTreeSet < String > > = HashMap :: new ( ) ;
44
53
for ( identifier, index) in self . ids . to_btreemap ( ) . iter ( ) {
45
- let ( directory, filename) = if identifier. contains ( '/' ) {
46
- let ( directory, filename) = identifier. rsplit_once ( '/' ) . expect ( "'/' must exist" ) ;
47
- let identifier_dir = zoneinfo_debug_path. join ( directory) ;
48
- fs:: create_dir_all ( identifier_dir. clone ( ) ) ?;
49
- ( identifier_dir, filename)
54
+ if let Some ( id_set) = tzif_ids. get_mut ( index) {
55
+ id_set. insert ( identifier. clone ( ) ) ;
50
56
} else {
51
- ( zoneinfo_debug_path. clone ( ) , identifier. as_str ( ) )
52
- } ;
53
- let mut filepath = directory. join ( filename) ;
54
- filepath. set_extension ( "json" ) ;
55
- let json = serde_json:: to_string_pretty ( & self . tzifs [ * index] ) ?;
56
- fs:: write ( filepath, json) ?;
57
+ tzif_ids. insert ( * index, BTreeSet :: from ( [ identifier. clone ( ) ] ) ) ;
58
+ }
59
+ }
60
+
61
+ let tzif_dir_path = zoneinfo_debug_path. join ( "tzifs" ) ;
62
+ fs:: create_dir_all ( tzif_dir_path. clone ( ) ) ?;
63
+
64
+ let mut id_map: BTreeMap < String , String > = BTreeMap :: new ( ) ;
65
+ for ( id, tzif) in self . tzifs . iter ( ) . enumerate ( ) {
66
+ let mut tzif_data = serde_json:: Map :: new ( ) ;
67
+ let id_set = tzif_ids. get ( & id) . unwrap ( ) ;
68
+ tzif_data. insert ( "ids" . into ( ) , serde_json:: to_value ( id_set) ?) ;
69
+ tzif_data. insert ( "tzif" . into ( ) , serde_json:: to_value ( & tzif) ?) ;
70
+ let filename = format ! ( "tzif-{}-{}.json" , hash_ids( id_set) , hash_tzif( & tzif) ) ;
71
+ let filepath = tzif_dir_path. join ( filename. clone ( ) ) ;
72
+ for id in id_set {
73
+ id_map. insert ( id. clone ( ) , filename. clone ( ) ) ;
74
+ }
75
+ fs:: write ( filepath, serde_json:: to_string_pretty ( & tzif_data) ?) ?;
57
76
}
58
77
78
+ fs:: write (
79
+ map_file,
80
+ format ! ( "{}\n " , serde_json:: to_string_pretty( & id_map) ?) ,
81
+ ) ?;
82
+
59
83
// TODO: Add version
60
84
Ok ( ( ) )
61
85
}
62
86
}
63
87
88
+ fn hash_ids ( set : & BTreeSet < String > ) -> String {
89
+ let mut hasher = DefaultHasher :: new ( ) ;
90
+ set. hash ( & mut hasher) ;
91
+ format ! ( "{:x}" , hasher. finish( ) )
92
+ }
93
+
94
+ fn hash_tzif ( tzif : & ZeroTzifULE ) -> String {
95
+ let mut hasher = DefaultHasher :: new ( ) ;
96
+ tzif. transitions ( ) . as_bytes ( ) . hash ( & mut hasher) ;
97
+ format ! ( "{:x}" , hasher. finish( ) )
98
+ }
99
+
64
100
impl BakedDataProvider for IanaIdentifierNormalizer < ' _ > {
65
101
fn write_data ( & self , data_path : & Path ) -> io:: Result < ( ) > {
66
102
fs:: create_dir_all ( data_path) ?;
0 commit comments