aboutsummaryrefslogtreecommitdiff
path: root/apps/cassiopeia/src
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-12-11 17:58:39 +0000
committerMx Kookie <kookie@spacekookie.de>2020-12-21 05:19:49 +0100
commitd40e014aebc778939ae8d9afae225b7d4f6cc949 (patch)
treefa79d54a901c757149b90f8bdf329e954b432bc7 /apps/cassiopeia/src
parent717c5ccff4a03c3f459456586bcbc28cd88f6709 (diff)
cassiopeia: adding more types to the time file abstraction
Diffstat (limited to 'apps/cassiopeia/src')
-rw-r--r--apps/cassiopeia/src/data.rs66
-rw-r--r--apps/cassiopeia/src/format/mod.rs7
-rw-r--r--apps/cassiopeia/src/format/parser.rs22
-rw-r--r--apps/cassiopeia/src/main.rs3
4 files changed, 77 insertions, 21 deletions
diff --git a/apps/cassiopeia/src/data.rs b/apps/cassiopeia/src/data.rs
index 8ebc67f016c5..3911345109ca 100644
--- a/apps/cassiopeia/src/data.rs
+++ b/apps/cassiopeia/src/data.rs
@@ -5,25 +5,79 @@
//! analysis tasks.
use crate::format::LineCfg;
-use chrono::{Date, DateTime, FixedOffset as Offset};
+use chrono::{DateTime, Duration, FixedOffset as Offset, NaiveDate};
use std::collections::BTreeMap;
-#[derive(Default)]
+#[derive(Debug, Default)]
pub struct TimeFile {
+ /// Raw line buffers to echo back into the file
+ lines: Vec<LineCfg>,
+ /// A parsed header structure
header: BTreeMap<String, String>,
+ /// A parsed session structure
sessions: Vec<Session>,
- invoices: Vec<Date<Offset>>,
+ /// A parsed invoice list
+ invoices: Vec<Invoice>,
}
impl TimeFile {
- pub(crate) fn append(self, line: LineCfg) -> Self {
- println!("{:?}", line);
+ pub(crate) fn append(mut self, line: LineCfg) -> Self {
+ let lo = self.lines.len();
+ match line {
+ LineCfg::Header(ref header) => self.header = header.clone(),
+ LineCfg::Start(Some(time)) => self.sessions.push(Session::start(time, lo)),
+ LineCfg::Stop(Some(time)) => self.get_last_session().stop(time, lo),
+ LineCfg::Invoice(Some(date)) => self.invoices.push(Invoice::new(date, lo)),
+ _ => {}
+ }
+ self.lines.push(line);
self
}
+
+ fn get_last_session(&mut self) -> &mut Session {
+ self.sessions.last_mut().unwrap()
+ }
}
+#[derive(Debug)]
pub struct Session {
start: DateTime<Offset>,
- stop: DateTime<Offset>,
+ stop: Option<DateTime<Offset>>,
+ /// Track the lines this session took place in
+ lines: (usize, usize),
+}
+
+impl Session {
+ /// Create a new session with a start time
+ fn start(start: DateTime<Offset>, line: usize) -> Self {
+ Self {
+ start,
+ stop: None,
+ lines: (line, 0),
+ }
+ }
+
+ /// Finalise a session with a stop time
+ fn stop(&mut self, stop: DateTime<Offset>, line: usize) {
+ self.stop = Some(stop);
+ self.lines.1 = line;
+ }
+
+ /// Get the length of the session, if it was already finished
+ pub fn length(&self) -> Option<Duration> {
+ self.stop.map(|stop| stop - self.start)
+ }
+}
+
+#[derive(Debug)]
+pub struct Invoice {
+ date: NaiveDate,
+ line: usize,
+}
+
+impl Invoice {
+ fn new(date: NaiveDate, line: usize) -> Self {
+ Self { date, line }
+ }
}
diff --git a/apps/cassiopeia/src/format/mod.rs b/apps/cassiopeia/src/format/mod.rs
index beab2f7aac66..bac0445d8387 100644
--- a/apps/cassiopeia/src/format/mod.rs
+++ b/apps/cassiopeia/src/format/mod.rs
@@ -9,7 +9,10 @@ pub(crate) use parser::LineCfg;
use crate::TimeFile;
use std::{fs::File, io::Read};
-pub(crate) fn load_file(path: &str) {
+/// The cassiopeia parser/generator version to be written back into the file
+pub const CASS_VERSION: &str = env!("CARGO_PKG_VERSION");
+
+pub(crate) fn load_file(path: &str) -> TimeFile {
let mut f = File::open(path).unwrap();
let mut content = String::new();
f.read_to_string(&mut content).unwrap();
@@ -21,5 +24,5 @@ pub(crate) fn load_file(path: &str) {
.map(|line| lexer::lex(line))
.map(|lex| parser::parse(lex))
.filter(|line| line.valid())
- .fold(TimeFile::default(), |file, line| file.append(line));
+ .fold(TimeFile::default(), |file, line| file.append(line))
}
diff --git a/apps/cassiopeia/src/format/parser.rs b/apps/cassiopeia/src/format/parser.rs
index cc4b1b7c77df..bb2c56be0f33 100644
--- a/apps/cassiopeia/src/format/parser.rs
+++ b/apps/cassiopeia/src/format/parser.rs
@@ -4,8 +4,7 @@
//! parsed time file.
use crate::format::{LineLexer, LineToken, Token};
-use chrono::{DateTime, FixedOffset as Offset};
-use logos::Lexer;
+use chrono::{NaiveDate, DateTime, FixedOffset as Offset};
use std::collections::BTreeMap;
use std::iter::Iterator;
@@ -19,9 +18,7 @@ pub enum LineCfg {
/// A session stop line with a date and time
Stop(Option<DateTime<Offset>>),
/// An invoice line with a date
- Invoice(Option<DateTime<Offset>>),
- /// An empty line
- Empty,
+ Invoice(Option<NaiveDate>),
/// A temporary value that is invalid
#[doc(hidden)]
Ignore,
@@ -39,7 +36,7 @@ impl LineCfg {
pub(crate) fn parse<'l>(lex: LineLexer<'l>) -> LineCfg {
use LineCfg::*;
use Token as T;
-
+
#[cfg_attr(rustfmt, rustfmt_skip)]
lex.get_all().into_iter().fold(Ignore, |cfg, tok| match (cfg, tok) {
// If the first token is a comment, we ignore it
@@ -52,13 +49,10 @@ pub(crate) fn parse<'l>(lex: LineLexer<'l>) -> LineCfg {
// If the first token _was_ a keyword, fill in the data
(Header(map), LineToken { tt: T::HeaderData, slice }) => Header(append_data(map, slice)),
- (Start(_), LineToken { tt: T::Date, slice }) => Start(parse_date(slice)),
- (Stop(_), LineToken { tt: T::Date, slice }) => Stop(parse_date(slice)),
+ (Start(_), LineToken { tt: T::Date, slice }) => Start(parse_datetime(slice)),
+ (Stop(_), LineToken { tt: T::Date, slice }) => Stop(parse_datetime(slice)),
(Invoice(_), LineToken { tt: T::Date, slice }) => Invoice(parse_date(slice)),
- // Pass empty lines through,
- (Empty, _) => Empty,
-
// Ignore everything else (which will be filtered)
_ => Ignore,
})
@@ -70,9 +64,13 @@ fn append_data(mut map: BTreeMap<String, String>, slice: &str) -> BTreeMap<Strin
map
}
-fn parse_date(slice: &str) -> Option<DateTime<Offset>> {
+fn parse_datetime(slice: &str) -> Option<DateTime<Offset>> {
Some(
DateTime::parse_from_str(slice, "%Y-%m-%d %H:%M:%S%:z")
.expect("Failed to parse date; invalid format!"),
)
}
+
+fn parse_date(slice: &str) -> Option<NaiveDate> {
+ Some(NaiveDate::parse_from_str(slice, "%Y-%m-%d").expect("Failed to parse date; invalid format!"))
+}
diff --git a/apps/cassiopeia/src/main.rs b/apps/cassiopeia/src/main.rs
index b28f3c3438f7..ff942731c3d5 100644
--- a/apps/cassiopeia/src/main.rs
+++ b/apps/cassiopeia/src/main.rs
@@ -4,5 +4,6 @@ mod data;
pub use data::{TimeFile, Session};
fn main() {
- format::load_file("/home/projects/clients/nyantec-nix-workshops/time.cass")
+ let file = format::load_file("/home/projects/clients/nyantec-nix-workshops/time.cass");
+
}