aboutsummaryrefslogtreecommitdiff
path: root/apps/cassiopeia/src/format/ir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/cassiopeia/src/format/ir.rs')
-rw-r--r--apps/cassiopeia/src/format/ir.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/apps/cassiopeia/src/format/ir.rs b/apps/cassiopeia/src/format/ir.rs
new file mode 100644
index 000000000000..32922ec079e7
--- /dev/null
+++ b/apps/cassiopeia/src/format/ir.rs
@@ -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;
+}