Merge pull request #309 from matthiasbeyer/libimagdiary/init
Libimagdiary/init
This commit is contained in:
commit
c099fc7270
10 changed files with 636 additions and 0 deletions
26
libimagdiary/Cargo.toml
Normal file
26
libimagdiary/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
[package]
|
||||||
|
name = "libimagdiary"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = "0.2"
|
||||||
|
log = "0.3.5"
|
||||||
|
semver = "0.2"
|
||||||
|
toml = "0.1.25"
|
||||||
|
regex = "0.1"
|
||||||
|
lazy_static = "0.2"
|
||||||
|
itertools = "0.4"
|
||||||
|
|
||||||
|
[dependencies.libimagstore]
|
||||||
|
path = "../libimagstore"
|
||||||
|
|
||||||
|
[dependencies.libimagerror]
|
||||||
|
path = "../libimagerror"
|
||||||
|
|
||||||
|
[dependencies.libimagutil]
|
||||||
|
path = "../libimagutil"
|
||||||
|
|
||||||
|
[dependencies.libimagrt]
|
||||||
|
path = "../libimagrt"
|
||||||
|
|
19
libimagdiary/src/config.rs
Normal file
19
libimagdiary/src/config.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use toml::Value;
|
||||||
|
|
||||||
|
use libimagrt::runtime::Runtime;
|
||||||
|
|
||||||
|
pub fn get_default_diary_name(rt: &Runtime) -> Option<String> {
|
||||||
|
get_diary_config_section(rt)
|
||||||
|
.and_then(|config| {
|
||||||
|
match config.lookup("default_diary") {
|
||||||
|
Some(&Value::String(ref s)) => Some(s.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_diary_config_section<'a>(rt: &'a Runtime) -> Option<&'a Value> {
|
||||||
|
rt.config()
|
||||||
|
.map(|config| config.config())
|
||||||
|
.and_then(|config| config.lookup("diary"))
|
||||||
|
}
|
109
libimagdiary/src/diary.rs
Normal file
109
libimagdiary/src/diary.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use libimagstore::store::Store;
|
||||||
|
use libimagstore::storeid::IntoStoreId;
|
||||||
|
use libimagerror::trace::trace_error;
|
||||||
|
|
||||||
|
use chrono::offset::local::Local;
|
||||||
|
use chrono::Datelike;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
|
||||||
|
use entry::Entry;
|
||||||
|
use diaryid::DiaryId;
|
||||||
|
use error::DiaryError as DE;
|
||||||
|
use error::DiaryErrorKind as DEK;
|
||||||
|
use result::Result;
|
||||||
|
use iter::DiaryEntryIterator;
|
||||||
|
use is_in_diary::IsInDiary;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Diary<'a> {
|
||||||
|
store: &'a Store,
|
||||||
|
name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Diary<'a> {
|
||||||
|
|
||||||
|
pub fn open(store: &'a Store, name: &'a str) -> Diary<'a> {
|
||||||
|
Diary {
|
||||||
|
store: store,
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create or get a new entry for today
|
||||||
|
pub fn new_entry_today(&self) -> Result<Entry> {
|
||||||
|
let dt = Local::now();
|
||||||
|
let ndt = dt.naive_local();
|
||||||
|
let id = DiaryId::new(String::from(self.name), ndt.year(), ndt.month(), ndt.day(), 0, 0);
|
||||||
|
self.new_entry_by_id(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_entry_by_id(&self, id: DiaryId) -> Result<Entry> {
|
||||||
|
self.retrieve(id.with_diary_name(String::from(self.name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn retrieve(&self, id: DiaryId) -> Result<Entry> {
|
||||||
|
self.store
|
||||||
|
.retrieve(id.into_storeid())
|
||||||
|
.map(|fle| Entry::new(fle))
|
||||||
|
.map_err(|e| DE::new(DEK::StoreWriteError, Some(Box::new(e))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get an iterator for iterating over all entries
|
||||||
|
pub fn entries(&self) -> Result<DiaryEntryIterator<'a>> {
|
||||||
|
self.store
|
||||||
|
.retrieve_for_module("diary")
|
||||||
|
.map(|iter| DiaryEntryIterator::new(self.name, self.store, iter))
|
||||||
|
.map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_entry(&self, entry: Entry) -> Result<()> {
|
||||||
|
if !entry.is_in_diary(self.name) {
|
||||||
|
return Err(DE::new(DEK::EntryNotInDiary, None));
|
||||||
|
}
|
||||||
|
let id = entry.get_location().clone();
|
||||||
|
drop(entry);
|
||||||
|
|
||||||
|
self.store.delete(id)
|
||||||
|
.map_err(|e| DE::new(DEK::StoreWriteError, Some(Box::new(e))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_youngest_entry(&self) -> Option<Result<Entry>> {
|
||||||
|
match self.entries() {
|
||||||
|
Err(e) => Some(Err(e)),
|
||||||
|
Ok(entries) => {
|
||||||
|
entries.sorted_by(|a, b| {
|
||||||
|
match (a, b) {
|
||||||
|
(&Ok(ref a), &Ok(ref b)) => {
|
||||||
|
let a : NaiveDateTime = a.diary_id().into();
|
||||||
|
let b : NaiveDateTime = b.diary_id().into();
|
||||||
|
|
||||||
|
a.cmp(&b)
|
||||||
|
},
|
||||||
|
|
||||||
|
(&Ok(_), &Err(ref e)) => {
|
||||||
|
trace_error(e);
|
||||||
|
Ordering::Less
|
||||||
|
},
|
||||||
|
(&Err(ref e), &Ok(_)) => {
|
||||||
|
trace_error(e);
|
||||||
|
Ordering::Greater
|
||||||
|
},
|
||||||
|
(&Err(ref e1), &Err(ref e2)) => {
|
||||||
|
trace_error(e1);
|
||||||
|
trace_error(e2);
|
||||||
|
Ordering::Equal
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}).into_iter().next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &'a str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
217
libimagdiary/src/diaryid.rs
Normal file
217
libimagdiary/src/diaryid.rs
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
use std::convert::Into;
|
||||||
|
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||||
|
|
||||||
|
use chrono::naive::datetime::NaiveDateTime;
|
||||||
|
use chrono::naive::time::NaiveTime;
|
||||||
|
use chrono::naive::date::NaiveDate;
|
||||||
|
use chrono::Datelike;
|
||||||
|
use chrono::Timelike;
|
||||||
|
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
|
use libimagstore::storeid::IntoStoreId;
|
||||||
|
|
||||||
|
use module_path::ModuleEntryPath;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DiaryId {
|
||||||
|
name: String,
|
||||||
|
year: i32,
|
||||||
|
month: u32,
|
||||||
|
day: u32,
|
||||||
|
hour: u32,
|
||||||
|
minute: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DiaryId {
|
||||||
|
|
||||||
|
pub fn new(name: String, y: i32, m: u32, d: u32, h: u32, min: u32) -> DiaryId {
|
||||||
|
DiaryId {
|
||||||
|
name: name,
|
||||||
|
year: y,
|
||||||
|
month: m,
|
||||||
|
day: d,
|
||||||
|
hour: h,
|
||||||
|
minute: min,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_datetime<DT: Datelike + Timelike>(diary_name: String, dt: DT) -> DiaryId {
|
||||||
|
DiaryId::new(diary_name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diary_name(&self) -> &String {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn year(&self) -> i32 {
|
||||||
|
self.year
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn month(&self) -> u32 {
|
||||||
|
self.month
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn day(&self) -> u32 {
|
||||||
|
self.day
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hour(&self) -> u32 {
|
||||||
|
self.hour
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn minute(&self) -> u32 {
|
||||||
|
self.minute
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_diary_name(mut self, name: String) -> DiaryId {
|
||||||
|
self.name = name;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_year(mut self, year: i32) -> DiaryId {
|
||||||
|
self.year = year;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_month(mut self, month: u32) -> DiaryId {
|
||||||
|
self.month = month;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_day(mut self, day: u32) -> DiaryId {
|
||||||
|
self.day = day;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_hour(mut self, hour: u32) -> DiaryId {
|
||||||
|
self.hour = hour;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_minute(mut self, minute: u32) -> DiaryId {
|
||||||
|
self.minute = minute;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn now(name: String) -> DiaryId {
|
||||||
|
use chrono::offset::local::Local;
|
||||||
|
|
||||||
|
let now = Local::now();
|
||||||
|
let now_date = now.date().naive_local();
|
||||||
|
let now_time = now.time();
|
||||||
|
let dt = NaiveDateTime::new(now_date, now_time);
|
||||||
|
|
||||||
|
DiaryId::new(name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DiaryId {
|
||||||
|
|
||||||
|
/// Create a default DiaryId which is a diaryid for a diary named "default" with
|
||||||
|
/// time = 0000-00-00 00:00:00
|
||||||
|
fn default() -> DiaryId {
|
||||||
|
let dt = NaiveDateTime::new(NaiveDate::from_ymd(0, 0, 0), NaiveTime::from_hms(0, 0, 0));
|
||||||
|
DiaryId::from_datetime(String::from("default"), dt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoStoreId for DiaryId {
|
||||||
|
|
||||||
|
fn into_storeid(self) -> StoreId {
|
||||||
|
let s : String = self.into();
|
||||||
|
ModuleEntryPath::new(s).into_storeid()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<String> for DiaryId {
|
||||||
|
|
||||||
|
fn into(self) -> String {
|
||||||
|
format!("{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
|
||||||
|
self.name, self.year, self.month, self.day, self.hour, self.minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DiaryId {
|
||||||
|
|
||||||
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
|
write!(fmt, "{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
|
||||||
|
self.name, self.year, self.month, self.day, self.hour, self.minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<NaiveDateTime> for DiaryId {
|
||||||
|
|
||||||
|
fn into(self) -> NaiveDateTime {
|
||||||
|
let d = NaiveDate::from_ymd(self.year, self.month, self.day);
|
||||||
|
let t = NaiveTime::from_hms(self.hour, self.minute, 0);
|
||||||
|
NaiveDateTime::new(d, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromStoreId : Sized {
|
||||||
|
|
||||||
|
fn from_storeid(&StoreId) -> Option<Self>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::path::Component;
|
||||||
|
|
||||||
|
fn component_to_str<'a>(com: Component<'a>) -> Option<&'a str> {
|
||||||
|
match com {
|
||||||
|
Component::Normal(s) => Some(s),
|
||||||
|
_ => None
|
||||||
|
}.and_then(|s| s.to_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStoreId for DiaryId {
|
||||||
|
|
||||||
|
fn from_storeid(s: &StoreId) -> Option<DiaryId> {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
let mut cmps = s.components().rev();
|
||||||
|
let (hour, minute) = match cmps.next().and_then(component_to_str)
|
||||||
|
.and_then(|time| {
|
||||||
|
let mut time = time.split(":");
|
||||||
|
let hour = time.next().and_then(|s| FromStr::from_str(s).ok());
|
||||||
|
let minute = time.next()
|
||||||
|
.and_then(|s| s.split("~").next())
|
||||||
|
.and_then(|s| FromStr::from_str(s).ok());
|
||||||
|
|
||||||
|
debug!("Hour = {:?}", hour);
|
||||||
|
debug!("Minute = {:?}", minute);
|
||||||
|
|
||||||
|
match (hour, minute) {
|
||||||
|
(Some(h), Some(m)) => Some((h, m)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Some(s) => s,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let day :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
|
||||||
|
let month :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
|
||||||
|
let year :Option<i32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
|
||||||
|
let name = cmps.next().and_then(component_to_str).map(String::from);
|
||||||
|
|
||||||
|
debug!("Day = {:?}", day);
|
||||||
|
debug!("Month = {:?}", month);
|
||||||
|
debug!("Year = {:?}", year);
|
||||||
|
debug!("Name = {:?}", name);
|
||||||
|
|
||||||
|
let day = if day.is_none() { return None; } else { day.unwrap() };
|
||||||
|
let month = if month.is_none() { return None; } else { month.unwrap() };
|
||||||
|
let year = if year.is_none() { return None; } else { year.unwrap() };
|
||||||
|
let name = if name.is_none() { return None; } else { name.unwrap() };
|
||||||
|
|
||||||
|
Some(DiaryId::new(name, year, month, day, hour, minute))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
71
libimagdiary/src/entry.rs
Normal file
71
libimagdiary/src/entry.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
|
use libimagstore::store::FileLockEntry;
|
||||||
|
use libimagrt::edit::Edit;
|
||||||
|
use libimagrt::edit::EditResult;
|
||||||
|
use libimagrt::runtime::Runtime;
|
||||||
|
|
||||||
|
use diaryid::DiaryId;
|
||||||
|
use diaryid::FromStoreId;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Entry<'a>(FileLockEntry<'a>);
|
||||||
|
|
||||||
|
impl<'a> Deref for Entry<'a> {
|
||||||
|
type Target = FileLockEntry<'a>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &FileLockEntry<'a> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DerefMut for Entry<'a> {
|
||||||
|
|
||||||
|
fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Entry<'a> {
|
||||||
|
|
||||||
|
pub fn new(fle: FileLockEntry<'a>) -> Entry<'a> {
|
||||||
|
Entry(fle)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the diary id for this entry.
|
||||||
|
///
|
||||||
|
/// TODO: calls Option::unwrap() as it assumes that an existing Entry has an ID that is parsable
|
||||||
|
pub fn diary_id(&self) -> DiaryId {
|
||||||
|
DiaryId::from_storeid(&self.0.get_location().clone()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Into<FileLockEntry<'a>> for Entry<'a> {
|
||||||
|
|
||||||
|
fn into(self) -> FileLockEntry<'a> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<FileLockEntry<'a>> for Entry<'a> {
|
||||||
|
|
||||||
|
fn from(fle: FileLockEntry<'a>) -> Entry<'a> {
|
||||||
|
Entry::new(fle)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Edit for Entry<'a> {
|
||||||
|
|
||||||
|
fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
|
||||||
|
self.0.edit_content(rt)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
16
libimagdiary/src/error.rs
Normal file
16
libimagdiary/src/error.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
generate_error_module!(
|
||||||
|
generate_error_types!(DiaryError, DiaryErrorKind,
|
||||||
|
StoreWriteError => "Error writing store",
|
||||||
|
StoreReadError => "Error reading store",
|
||||||
|
CannotFindDiary => "Cannot find diary",
|
||||||
|
CannotCreateNote => "Cannot create Note object for diary entry",
|
||||||
|
DiaryEditError => "Cannot edit diary entry",
|
||||||
|
PathConversionError => "Error while converting paths internally",
|
||||||
|
EntryNotInDiary => "Entry not in Diary",
|
||||||
|
IOError => "IO Error"
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
pub use self::error::DiaryError;
|
||||||
|
pub use self::error::DiaryErrorKind;
|
||||||
|
|
26
libimagdiary/src/is_in_diary.rs
Normal file
26
libimagdiary/src/is_in_diary.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use libimagstore::store::Entry;
|
||||||
|
|
||||||
|
pub trait IsInDiary {
|
||||||
|
|
||||||
|
fn is_in_diary(&self, name: &str) -> bool;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsInDiary for Entry {
|
||||||
|
|
||||||
|
fn is_in_diary(&self, name: &str) -> bool {
|
||||||
|
self.get_location().is_in_diary(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsInDiary for PathBuf {
|
||||||
|
|
||||||
|
fn is_in_diary(&self, name: &str) -> bool {
|
||||||
|
self.to_str().map(|s| s.contains(name)).unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
108
libimagdiary/src/iter.rs
Normal file
108
libimagdiary/src/iter.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
use std::fmt::{Debug, Formatter, Error as FmtError};
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
|
||||||
|
use libimagstore::store::Store;
|
||||||
|
use libimagstore::storeid::StoreIdIterator;
|
||||||
|
|
||||||
|
use diaryid::DiaryId;
|
||||||
|
use diaryid::FromStoreId;
|
||||||
|
use is_in_diary::IsInDiary;
|
||||||
|
use entry::Entry as DiaryEntry;
|
||||||
|
use error::DiaryError as DE;
|
||||||
|
use error::DiaryErrorKind as DEK;
|
||||||
|
use result::Result;
|
||||||
|
|
||||||
|
/// A iterator for iterating over diary entries
|
||||||
|
pub struct DiaryEntryIterator<'a> {
|
||||||
|
store: &'a Store,
|
||||||
|
name: &'a str,
|
||||||
|
iter: StoreIdIterator,
|
||||||
|
|
||||||
|
year: Option<i32>,
|
||||||
|
month: Option<u32>,
|
||||||
|
day: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Debug for DiaryEntryIterator<'a> {
|
||||||
|
|
||||||
|
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
|
||||||
|
write!(fmt, "DiaryEntryIterator<name = {}, year = {:?}, month = {:?}, day = {:?}>",
|
||||||
|
self.name, self.year, self.month, self.day)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DiaryEntryIterator<'a> {
|
||||||
|
|
||||||
|
pub fn new(diaryname: &'a str, store: &'a Store, iter: StoreIdIterator) -> DiaryEntryIterator<'a> {
|
||||||
|
DiaryEntryIterator {
|
||||||
|
store: store,
|
||||||
|
name: diaryname,
|
||||||
|
iter: iter,
|
||||||
|
|
||||||
|
year: None,
|
||||||
|
month: None,
|
||||||
|
day: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by year, get all diary entries for this year
|
||||||
|
pub fn year(mut self, year: i32) -> DiaryEntryIterator<'a> {
|
||||||
|
self.year = Some(year);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by month, get all diary entries for this month (every year)
|
||||||
|
pub fn month(mut self, month: u32) -> DiaryEntryIterator<'a> {
|
||||||
|
self.month = Some(month);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by day, get all diary entries for this day (every year, every year)
|
||||||
|
pub fn day(mut self, day: u32) -> DiaryEntryIterator<'a> {
|
||||||
|
self.day = Some(day);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for DiaryEntryIterator<'a> {
|
||||||
|
type Item = Result<DiaryEntry<'a>>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Result<DiaryEntry<'a>>> {
|
||||||
|
loop {
|
||||||
|
let next = self.iter.next();
|
||||||
|
debug!("Next element: {:?}", next);
|
||||||
|
if next.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let next = next.unwrap();
|
||||||
|
|
||||||
|
if next.is_in_diary(self.name) {
|
||||||
|
debug!("Seems to be in diary: {:?}", next);
|
||||||
|
let id = DiaryId::from_storeid(&next);
|
||||||
|
if id.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let id = id.unwrap();
|
||||||
|
|
||||||
|
let y = match self.year { None => true, Some(y) => y == id.year() };
|
||||||
|
let m = match self.month { None => true, Some(m) => m == id.month() };
|
||||||
|
let d = match self.day { None => true, Some(d) => d == id.day() };
|
||||||
|
|
||||||
|
if y && m && d {
|
||||||
|
return Some(self
|
||||||
|
.store
|
||||||
|
.retrieve(next)
|
||||||
|
.map(|fle| DiaryEntry::new(fle))
|
||||||
|
.map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e))))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug!("Not in the requested diary ({}): {:?}", self.name, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
39
libimagdiary/src/lib.rs
Normal file
39
libimagdiary/src/lib.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![deny(
|
||||||
|
dead_code,
|
||||||
|
non_camel_case_types,
|
||||||
|
non_snake_case,
|
||||||
|
path_statements,
|
||||||
|
trivial_numeric_casts,
|
||||||
|
unstable_features,
|
||||||
|
unused_allocation,
|
||||||
|
unused_import_braces,
|
||||||
|
unused_imports,
|
||||||
|
unused_must_use,
|
||||||
|
unused_mut,
|
||||||
|
unused_qualifications,
|
||||||
|
while_true,
|
||||||
|
)]
|
||||||
|
|
||||||
|
extern crate chrono;
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
#[macro_use] extern crate lazy_static;
|
||||||
|
extern crate semver;
|
||||||
|
extern crate toml;
|
||||||
|
extern crate regex;
|
||||||
|
extern crate itertools;
|
||||||
|
|
||||||
|
#[macro_use] extern crate libimagstore;
|
||||||
|
extern crate libimagutil;
|
||||||
|
#[macro_use] extern crate libimagerror;
|
||||||
|
extern crate libimagrt;
|
||||||
|
|
||||||
|
module_entry_path_mod!("diary", "0.1.0");
|
||||||
|
|
||||||
|
pub mod config;
|
||||||
|
pub mod error;
|
||||||
|
pub mod diaryid;
|
||||||
|
pub mod diary;
|
||||||
|
pub mod is_in_diary;
|
||||||
|
pub mod entry;
|
||||||
|
pub mod iter;
|
||||||
|
pub mod result;
|
5
libimagdiary/src/result.rs
Normal file
5
libimagdiary/src/result.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
use std::result::Result as RResult;
|
||||||
|
|
||||||
|
use error::DiaryError;
|
||||||
|
|
||||||
|
pub type Result<T> = RResult<T, DiaryError>;
|
Loading…
Reference in a new issue