use alloc::vec::Vec;
use indexmap::IndexSet;
use crate::compiler::CompiledTransitions;
#[derive(Debug)]
pub struct TzifBlockV2 {
pub transition_times: Vec<i64>,
pub transition_types: Vec<u8>,
pub local_time_types: Vec<LocalTimeRecord>, pub designations: Vec<char>,
}
impl TzifBlockV2 {
pub fn from_transition_data(data: &CompiledTransitions) -> Self {
let mut local_time_set = IndexSet::new();
let mut designation_set = DesignationSet::default();
let index = designation_set
.insert_and_retrieve_index(data.initial_record.designation.chars().collect());
local_time_set.insert(LocalTimeRecord {
offset: data.initial_record.offset,
is_dst: data.initial_record.saving.as_secs() != 0,
index: index as u8,
});
let mut transition_times = Vec::default();
let mut transition_types = Vec::default();
for transition in &data.transitions {
let index =
designation_set.insert_and_retrieve_index(transition.format.chars().collect());
let local_time_record = LocalTimeRecord {
offset: transition.offset,
is_dst: transition.dst,
index: index as u8,
};
transition_times.push(transition.at_time);
match local_time_set.get_index_of(&local_time_record) {
Some(i) => transition_types.push(i as u8),
None => {
let _ = local_time_set.insert(local_time_record);
transition_types.push(local_time_set.len() as u8 - 1);
}
}
}
let local_time_types = local_time_set.into_iter().collect::<Vec<LocalTimeRecord>>();
let designations = designation_set.to_vec();
Self {
transition_times,
transition_types,
local_time_types,
designations,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocalTimeRecord {
pub offset: i64,
pub is_dst: bool,
pub index: u8,
}
#[derive(Debug, Default, Clone)]
pub struct DesignationSet {
pub designations: IndexSet<Vec<char>>,
pub indices: Vec<usize>,
pub next_index: usize,
}
impl DesignationSet {
pub fn insert_and_retrieve_index(&mut self, mut designation: Vec<char>) -> usize {
designation.push('\0');
let Some(index) = self.designations.get_index_of(&designation) else {
let designation_len = designation.len();
let _ = self.designations.insert(designation);
let designation_index = self.next_index;
self.indices.push(designation_index);
self.next_index += designation_len;
return designation_index;
};
self.indices[index]
}
pub fn to_vec(self) -> Vec<char> {
self.designations
.into_iter()
.collect::<Vec<Vec<char>>>()
.concat()
}
}