use crate::{format::LineCfg, Date, Time, TimeFile};
use std::collections::BTreeMap;
pub(crate) type IrStream = Vec<IrItem>;
#[derive(Debug, Clone)]
pub(crate) struct IrItem {
pub(crate) tt: IrType,
pub(crate) lo: usize,
}
#[derive(Debug, Clone)]
pub(crate) enum IrType {
Header(BTreeMap<String, String>),
Start(Time),
Stop(Time),
Invoice(Date),
Ignore,
}
pub(crate) fn generate_ir(buf: impl Iterator<Item = LineCfg>) -> IrStream {
buf.enumerate().fold(vec![], |mut buf, (lo, item)| {
#[cfg_attr(rustfmt, rustfmt_skip)]
buf.push(match item {
LineCfg::Header(map) => IrItem { tt: IrType::Header(map.into_iter().map(|(k, v)| (k, v.replace(",", ""))).collect()), lo },
LineCfg::Start(Some(time)) => IrItem { tt: IrType::Start(time.into()), lo },
LineCfg::Stop(Some(time)) => IrItem { tt: IrType::Stop(time.into()), lo },
LineCfg::Invoice(Some(date)) => IrItem { tt: IrType::Invoice(date.into()), lo },
LineCfg::Ignore => IrItem { tt: IrType::Ignore, lo },
_ => IrItem { tt: IrType::Ignore, lo },
});
buf
})
}
pub(crate) trait MakeIr {
fn make_ir(&self) -> IrType;
}
pub(crate) fn clean_ir(ir: &mut IrStream) {
ir.remove(0);
if match ir.last() {
Some(IrItem {
tt: IrType::Ignore, ..
}) => true,
_ => false,
} {
ir.pop();
}
}
pub(crate) fn append_ir(ir: &mut IrStream, tt: IrType) {
let lo = ir.last().unwrap().lo;
ir.push(IrItem { tt, lo });
}
pub(crate) fn update_header(ir: &mut IrStream) {
ir.iter_mut().for_each(|item| match item.tt {
IrType::Header(ref mut map) if map.contains_key("version") => {
map.insert("version".into(), crate::meta::VERSION.into());
}
_ => {}
});
}