aboutsummaryrefslogtreecommitdiff
path: root/apps/koffice/libko/src/cass/data.rs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/koffice/libko/src/cass/data.rs')
-rw-r--r--apps/koffice/libko/src/cass/data.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/apps/koffice/libko/src/cass/data.rs b/apps/koffice/libko/src/cass/data.rs
new file mode 100644
index 000000000000..4ff4dc93020e
--- /dev/null
+++ b/apps/koffice/libko/src/cass/data.rs
@@ -0,0 +1,116 @@
+//! Typed time file for cassiopeia
+//!
+//! This data gets generated by the `format` module, and can later be
+//! used to generate new files, and perform various lookups and
+//! analysis tasks.
+
+use crate::cass::{
+ error::{ParseError, ParseResult, UserResult},
+ format::ir::{IrItem, IrType, MakeIr},
+ timeline::{Entry, Timeline},
+ Date, Time,
+};
+use chrono::{DateTime, Duration, FixedOffset as Offset, Local, NaiveDate};
+use std::collections::BTreeMap;
+
+#[derive(Clone, Debug, Default)]
+pub struct TimeFile {
+ /// A parsed header structure
+ pub(crate) header: BTreeMap<String, String>,
+ /// A parsed timeline of events
+ pub(crate) timeline: Timeline,
+}
+
+impl TimeFile {
+ pub fn project(&self) -> Option<&String> {
+ self.header.get("project")
+ }
+
+ pub fn client(&self) -> Option<&String> {
+ self.header.get("client")
+ }
+
+ /// Append entries to the timeline from the parsed IR
+ ///
+ /// Report any errors that occur back to the parser, that will
+ /// print a message to the user and terminate the program.
+ pub(crate) fn append(&mut self, line: IrItem) -> ParseResult<()> {
+ match line {
+ IrItem {
+ tt: IrType::Header(ref header),
+ ..
+ } => Ok(header.iter().for_each(|(k, v)| {
+ self.header.insert(k.clone(), v.clone());
+ })),
+ IrItem {
+ tt: IrType::Start(time),
+ lo,
+ } => Ok(self.timeline.start(time).map(|_| ())?),
+ IrItem {
+ tt: IrType::Stop(time),
+ lo,
+ } => Ok(self.timeline.stop(time).map(|_| ())?),
+ IrItem {
+ tt: IrType::Invoice(date),
+ lo,
+ } => Ok(self.timeline.invoice(date).map(|_| ())?),
+ _ => Err(ParseError::Unknown),
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Session {
+ start: Time,
+ stop: Option<Time>,
+}
+
+impl Session {
+ /// Create a new session with a start time
+ pub(crate) fn start(start: Time) -> Self {
+ Self { start, stop: None }
+ }
+
+ /// Finalise a session with a stop time
+ pub(crate) fn stop(&mut self, stop: Time) {
+ self.stop = Some(stop);
+ }
+
+ /// Check whether this session was already finished
+ pub fn finished(&self) -> bool {
+ self.stop.is_some()
+ }
+
+ /// Get the length of the session, if it was already finished
+ pub fn length(&self) -> Option<Duration> {
+ self.stop.as_ref().map(|stop| stop - &self.start)
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Invoice {
+ pub(crate) date: Date,
+}
+
+impl Invoice {
+ pub(crate) fn new(date: Date) -> Self {
+ Self { date }
+ }
+}
+
+/// Changes to the timeline are encoded in a delta
+pub enum Delta {
+ Start(Time),
+ Stop(Time),
+ Invoice(Date),
+}
+
+impl MakeIr for Delta {
+ fn make_ir(&self) -> IrType {
+ match self {
+ Self::Start(ref time) => IrType::Start(time.clone()),
+ Self::Stop(ref time) => IrType::Stop(time.clone()),
+ Self::Invoice(ref date) => IrType::Invoice(date.clone()),
+ }
+ }
+}