This allows a few things: a, it's a persistant format that we can mirror to disk again, AND can adapt because all type information is known, and it allows for new entries to be added to the IR more easily, without having to worry about exact formatting, or re-inferring order from the TimeFile abstraction.wip/yesman
parent
4c97f3208a
commit
236cf191b9
@ -0,0 +1,26 @@ |
||||
use crate::Time; |
||||
use chrono::{FixedOffset as Offset, NaiveDate}; |
||||
|
||||
/// A convenienc wrapper around [chrono::NaiveDate](chrono::NaiveDate)
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||
pub struct Date { |
||||
inner: NaiveDate, |
||||
} |
||||
|
||||
impl Date { |
||||
pub fn today() -> Self { |
||||
Self::from(Time::now().date()) |
||||
} |
||||
|
||||
pub(crate) fn from(d: chrono::Date<Offset>) -> Self { |
||||
Self { |
||||
inner: d.naive_local(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl From<NaiveDate> for Date { |
||||
fn from(inner: NaiveDate) -> Self { |
||||
Self { inner } |
||||
} |
||||
} |
@ -0,0 +1,63 @@ |
||||
use crate::{format::LineCfg, Date, Time, TimeFile}; |
||||
use std::collections::BTreeMap; |
||||
|
||||
/// A set of IR parsed items that makes up a whole cass file
|
||||
pub(crate) type IrStream = Vec<IrItem>; |
||||
|
||||
/// Intermediate representation for parsing and generating files
|
||||
///
|
||||
/// The CASS IR is largely based on the output of the parser's
|
||||
/// [`LineCfg`](crate::format::LineCfg), but with concrete types used
|
||||
/// in the data layer (namely [`Date`][date] and [`Time`][time]),
|
||||
/// while also keeping track of the line numbers to allow idempotent
|
||||
/// file changes.
|
||||
///
|
||||
/// Something not yet implemented is comment pass-through (this needs
|
||||
/// to happen in the parser first), but will likely be implemented in
|
||||
/// a future version.
|
||||
///
|
||||
/// [date]: crate::Date
|
||||
/// [time]: crate::Time
|
||||
#[derive(Debug, Clone)] |
||||
pub(crate) struct IrItem { |
||||
pub(crate) tt: IrType, |
||||
pub(crate) lo: usize, |
||||
} |
||||
|
||||
/// Disambiguate between different IR line types with their payload
|
||||
#[derive(Debug, Clone)] |
||||
pub(crate) enum IrType { |
||||
/// A line with parsed header information
|
||||
Header(BTreeMap<String, String>), |
||||
/// Start a session at a given timestapm
|
||||
Start(Time), |
||||
/// Stop a session at a given timestamp
|
||||
Stop(Time), |
||||
/// Invoice a block of previous work
|
||||
Invoice(Date), |
||||
/// An item that gets ignored
|
||||
Ignore, |
||||
} |
||||
|
||||
/// Generate a stream of IR items from the raw parser output
|
||||
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), 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 { |
||||
/// Make a new IR line from an object
|
||||
fn make_ir(&self) -> IrType; |
||||
} |
Loading…
Reference in new issue