Skip to content

Commit f0dd735

Browse files
committed
Implement zoneinfo parsing and tzif structures
It's time to finally tackle the zoneinfo and tzif sourcing issue. The work here lays the baseline for to handle sourcing. There's still a lot more to add, and maybe some bugs to uncover. But this is also major progress.
1 parent 49fa75b commit f0dd735

File tree

16 files changed

+12560
-3
lines changed

16 files changed

+12560
-3
lines changed

Cargo.lock

+37
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["diplomat-gen", "bakeddata", "provider", "temporal_capi"]
3+
members = ["diplomat-gen", "bakeddata", "provider", "temporal_capi", "zoneinfo"]
44

55
[workspace.package]
66
edition = "2021"

provider/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//!
44
55
mod tzdb;
6+
mod tzif;
67

78
pub use tzdb::{IanaDataError, IanaIdentifierNormalizer};
89

provider/src/tzdb.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ const ZONE_INFO_FILES: [&str; 9] = [
5353
];
5454

5555
pub struct TzdbDataProvider {
56-
version: String,
57-
data: Table,
56+
pub(crate) version: String,
57+
pub(crate) data: Table,
5858
}
5959

6060
impl TzdbDataProvider {

provider/src/tzif.rs

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//! A compact, zero copy TZif file.
2+
//!
3+
//! NOTE: This representation does not follow the TZif specification
4+
//! to full detail, but instead attempts to compress TZif data into
5+
//! a functional, data driven equivalent.
6+
7+
use parse_zoneinfo::table::Table;
8+
use std::{
9+
borrow::Cow,
10+
collections::{BTreeMap, BTreeSet},
11+
path::Path,
12+
};
13+
use zerotrie::{ZeroTrieBuildError, ZeroTrieSimpleAscii};
14+
use zerovec::{VarZeroVec, ZeroVec};
15+
16+
use crate::tzdb::TzdbDataProvider;
17+
18+
#[derive(Debug, Clone, yoke::Yokeable, databake::Bake, serde::Serialize)]
19+
#[databake(path = temporal_provider::tzif)]
20+
pub struct ZeroZoneInfo<'data> {
21+
// Why u16? It would suck to have to refactor because there are > 256 TZifs
22+
ids: ZeroTrieSimpleAscii<ZeroVec<'data, u8>>,
23+
24+
tzifs: VarZeroVec<'data, ZeroTzifULE>,
25+
}
26+
27+
#[zerovec::make_varule(ZeroTzifULE)]
28+
#[derive(PartialEq, Debug, Clone, yoke::Yokeable, serde::Serialize, databake::Bake)]
29+
#[zerovec::skip_derive(Ord)]
30+
#[zerovec::derive(Debug, Serialize)]
31+
#[databake(path = temporal_provider::tzif)]
32+
pub struct ZeroTzif<'data> {
33+
transitions: ZeroVec<'data, i64>,
34+
// NOTE: zoneinfo64 does a fun little bitmap str
35+
transition_types: ZeroVec<'data, u32>,
36+
types: ZeroVec<'data, i64>,
37+
posix: Cow<'data, str>,
38+
}
39+
40+
pub enum ZoneInfoDataError {
41+
Build(ZeroTrieBuildError),
42+
}
43+
44+
impl ZeroZoneInfo<'_> {
45+
pub fn build(tzdata: &Path) -> Result<Self, ZoneInfoDataError> {
46+
let provider = TzdbDataProvider::new(tzdata).unwrap();
47+
let mut identifiers = BTreeMap::default();
48+
let mut zones_set = BTreeSet::default();
49+
for zoneset_id in provider.data.zonesets.keys() {
50+
let _ = zones_set.insert(zoneset_id.clone());
51+
identifiers.insert(zoneset_id.clone(), zoneset_id.clone());
52+
}
53+
for (link, zone) in provider.data.links.iter() {
54+
let _ = zones_set.insert(zone.clone());
55+
identifiers.insert(link.clone(), zone.clone());
56+
}
57+
58+
let zones: Vec<String> = zones_set.iter().cloned().collect();
59+
60+
let identier_map: BTreeMap<Vec<u8>, usize> = identifiers
61+
.iter()
62+
.map(|(id, zoneid)| (id.as_bytes().to_vec(), zones.binary_search(zoneid).unwrap()))
63+
.collect();
64+
65+
let tzifs: Vec<ZeroTzif<'_>> = zones
66+
.iter()
67+
.map(|id| ZeroTzif::build(&provider.data, id))
68+
.collect();
69+
70+
let tzifs_zerovec: VarZeroVec<'static, ZeroTzifULE> = tzifs.as_slice().into();
71+
72+
let ids = ZeroTrieSimpleAscii::try_from(&identier_map)
73+
.map_err(ZoneInfoDataError::Build)?
74+
.convert_store();
75+
76+
Ok(ZeroZoneInfo {
77+
ids,
78+
tzifs: tzifs_zerovec,
79+
})
80+
}
81+
}
82+
83+
impl ZeroTzif<'_> {
84+
fn build(data: &Table, id: &str) -> Self {
85+
todo!()
86+
}
87+
}

zoneinfo/Cargo.toml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "zoneinfo"
3+
edition.workspace = true
4+
version.workspace = true
5+
rust-version.workspace = true
6+
authors.workspace = true
7+
license.workspace = true
8+
repository.workspace = true
9+
readme.workspace = true
10+
exclude.workspace = true
11+
12+
[dependencies]
13+
hashbrown = "0.15.2"
14+
15+
[dev-dependencies]
16+
tzif = { workspace = true }
17+
18+
[features]
19+
std = []

0 commit comments

Comments
 (0)