Merge pull request #1118 from matthiasbeyer/remove-imag-counter

Remove libimagcounter / imag-counter
This commit is contained in:
Matthias Beyer 2017-09-29 09:20:59 +02:00 committed by GitHub
commit d8055b4553
17 changed files with 3 additions and 1026 deletions

View file

@ -9,7 +9,6 @@ members = [
"bin/core/imag-tag", "bin/core/imag-tag",
"bin/core/imag-view", "bin/core/imag-view",
"bin/domain/imag-bookmark", "bin/domain/imag-bookmark",
"bin/domain/imag-counter",
"bin/domain/imag-diary", "bin/domain/imag-diary",
"bin/domain/imag-mail", "bin/domain/imag-mail",
"bin/domain/imag-notes", "bin/domain/imag-notes",
@ -19,7 +18,6 @@ members = [
"lib/core/libimagrt", "lib/core/libimagrt",
"lib/core/libimagstore", "lib/core/libimagstore",
"lib/domain/libimagbookmark", "lib/domain/libimagbookmark",
"lib/domain/libimagcounter",
"lib/domain/libimagdiary", "lib/domain/libimagdiary",
"lib/domain/libimagmail", "lib/domain/libimagmail",
"lib/domain/libimagnotes", "lib/domain/libimagnotes",

View file

@ -1,25 +0,0 @@
[package]
name = "imag-counter"
version = "0.5.0"
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
description = "Part of the imag core distribution: imag-counter command"
keywords = ["imag", "PIM", "personal", "information", "management"]
readme = "../../../README.md"
license = "LGPL-2.1"
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
repository = "https://github.com/matthiasbeyer/imag"
homepage = "http://imag-pim.org"
[dependencies]
clap = ">=2.17"
log = "0.3"
version = "2.0.1"
libimagrt = { version = "0.5.0", path = "../../../lib/core/libimagrt" }
libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" }
libimagutil = { version = "0.5.0", path = "../../../lib/etc/libimagutil" }
libimagcounter = { version = "0.5.0", path = "../../../lib/domain/libimagcounter" }

View file

@ -1 +0,0 @@
../../../doc/src/04020-module-counter.md

View file

@ -1,50 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::str::FromStr;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagcounter::counter::Counter;
use libimagcounter::counter::CounterUnit;
pub fn create(rt: &Runtime) {
rt.cli()
.subcommand_matches("create")
.map(|scmd| {
debug!("Found 'create' subcommand...");
let name = scmd.value_of("name").unwrap(); // safe because clap enforces
let init : i64 = scmd
.value_of("initval")
.and_then(|i| FromStr::from_str(i).ok())
.unwrap_or(0);
let unit = scmd
.value_of("unit")
.map(CounterUnit::new);
Counter::new(rt.store(), String::from(name), init)
.and_then(|c| c.with_unit(unit))
.unwrap_or_else(|e| {
warn!("Could not create Counter '{}' with initial value '{}'", name, init);
trace_error_exit(&e, 1);
});
});
}

View file

@ -1,39 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagcounter::counter::Counter;
pub fn delete(rt: &Runtime) {
rt.cli()
.subcommand_matches("delete")
.map(|scmd| {
debug!("Found 'delete' subcommand...");
let name = String::from(scmd.value_of("name").unwrap()); // safe because clap enforces
if let Err(e) = Counter::delete(name, rt.store()) {
trace_error_exit(&e, 1);
}
info!("Ok");
});
}

View file

@ -1,174 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::collections::BTreeMap;
use std::fmt::{Display, Formatter, Error};
use std::io::Write;
use std::io::stderr;
use std::io::stdin;
use std::process::exit;
use std::result::Result as RResult;
use libimagcounter::counter::Counter;
use libimagcounter::error::CounterError;
use libimagrt::runtime::Runtime;
use libimagutil::key_value_split::IntoKeyValue;
use libimagutil::warn_exit::warn_exit;
use libimagerror::trace::{trace_error, trace_error_exit};
type Result<T> = RResult<T, CounterError>;
pub fn interactive(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("interactive");
if scmd.is_none() {
warn_exit("No subcommand", 1);
}
let scmd = scmd.unwrap();
debug!("Found 'interactive' command");
let mut pairs : BTreeMap<char, Binding> = BTreeMap::new();
for spec in scmd.values_of("spec").unwrap() {
match compute_pair(rt, &spec) {
Ok((k, v)) => { pairs.insert(k, v); },
Err(e) => { trace_error(&e); },
}
}
if !has_quit_binding(&pairs) {
pairs.insert('q', Binding::Function(String::from("quit"), Box::new(quit)));
}
stderr().flush().ok();
loop {
println!("---");
for (k, v) in &pairs {
println!("\t[{}] => {}", k, v);
}
println!("---");
print!("counter > ");
let mut input = String::new();
if let Err(e) = stdin().read_line(&mut input) {
trace_error_exit(&e, 1);
}
let cont = if !input.is_empty() {
let increment = match input.chars().next() { Some('-') => false, _ => true };
input.chars().all(|chr| {
match pairs.get_mut(&chr) {
Some(&mut Binding::Counter(ref mut ctr)) => {
if increment {
debug!("Incrementing");
if let Err(e) = ctr.inc() {
trace_error(&e);
}
} else {
debug!("Decrementing");
if let Err(e) = ctr.dec() {
trace_error(&e);
}
}
true
},
Some(&mut Binding::Function(ref name, ref f)) => {
debug!("Calling {}", name);
f()
},
None => true,
}
})
} else {
println!("No input...");
println!("\tUse a single character to increment the counter which is bound to it");
println!("\tUse 'q' (or the character bound to quit()) to exit");
println!("\tPrefix the line with '-' to decrement instead of increment the counters");
println!("");
true
};
if !cont {
break;
}
}
}
fn has_quit_binding(pairs: &BTreeMap<char, Binding>) -> bool {
pairs.iter()
.any(|(_, bind)| {
match *bind {
Binding::Function(ref name, _) => name == "quit",
_ => false,
}
})
}
enum Binding<'a> {
Counter(Counter<'a>),
Function(String, Box<Fn() -> bool>),
}
impl<'a> Display for Binding<'a> {
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), Error> {
match *self {
Binding::Counter(ref c) => {
match c.name() {
Ok(name) => {
try!(write!(fmt, "{}", name));
Ok(())
},
Err(e) => {
trace_error(&e);
Ok(()) // TODO: Find a better way to escalate here.
},
}
},
Binding::Function(ref name, _) => write!(fmt, "{}()", name),
}
}
}
fn compute_pair<'a>(rt: &'a Runtime, spec: &str) -> Result<(char, Binding<'a>)> {
let kv = String::from(spec).into_kv();
if kv.is_none() {
warn_exit("Key-Value parsing failed!", 1);
}
let kv = kv.unwrap();
let (k, v) = kv.into();
if !k.len() == 1 {
// We have a key which is not only a single character!
exit(1);
}
if v == "quit" {
// TODO uncaught unwrap()
Ok((k.chars().next().unwrap(), Binding::Function(String::from("quit"), Box::new(quit))))
} else {
// TODO uncaught unwrap()
Counter::load(v, rt.store()).and_then(|ctr| Ok((k.chars().next().unwrap(), Binding::Counter(ctr))))
}
}
fn quit() -> bool {
false
}

View file

@ -1,54 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use libimagrt::runtime::Runtime;
use libimagerror::trace::{MapErrTrace, trace_error};
use libimagcounter::counter::Counter;
pub fn list(rt: &Runtime) {
rt.cli()
.subcommand_matches("list")
.map(|_| {
debug!("Found 'list' subcommand...");
Counter::all_counters(rt.store()).map(|iterator| {
for counter in iterator {
counter.map(|c| {
let name = c.name();
let value = c.value();
let unit = c.unit();
if name.is_err() {
trace_error(&name.unwrap_err());
} else if value.is_err() {
trace_error(&value.unwrap_err());
} else if unit.is_none() {
println!("{} - {}", name.unwrap(), value.unwrap());
} else {
println!("{} - {} {}", name.unwrap(), value.unwrap(), unit.unwrap());
}
})
.map_err_trace()
.ok();
}
})
.map_err_trace()
});
}

View file

@ -1,139 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#![deny(
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,
)]
#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate clap;
extern crate libimagcounter;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;
use std::process::exit;
use std::str::FromStr;
use libimagrt::setup::generate_runtime_setup;
use libimagcounter::counter::Counter;
use libimagerror::trace::MapErrTrace;
use libimagutil::key_value_split::IntoKeyValue;
use libimagutil::info_result::*;
mod create;
mod delete;
mod interactive;
mod list;
mod ui;
use ui::build_ui;
use create::create;
use delete::delete;
use interactive::interactive;
use list::list;
enum Action {
Inc,
Dec,
Reset,
Set,
}
fn main() {
let rt = generate_runtime_setup("imag-counter",
&version!()[..],
"Counter tool to count things",
build_ui);
rt.cli()
.subcommand_name()
.map_or_else(|| {
let (action, name) = {
if rt.cli().is_present("increment") {
(Action::Inc, rt.cli().value_of("increment").unwrap())
} else if rt.cli().is_present("decrement") {
(Action::Dec, rt.cli().value_of("decrement").unwrap())
} else if rt.cli().is_present("reset") {
(Action::Reset, rt.cli().value_of("reset").unwrap())
} else /* rt.cli().is_present("set") */ {
(Action::Set, rt.cli().value_of("set").unwrap())
}
};
match action {
Action::Inc => {
Counter::load(String::from(name), rt.store())
.map(|mut c| c.inc().map_err_trace_exit(1).map_info_str("Ok"))
},
Action::Dec => {
Counter::load(String::from(name), rt.store())
.map(|mut c| c.dec().map_err_trace_exit(1).map_info_str("Ok"))
},
Action::Reset => {
Counter::load(String::from(name), rt.store())
.map(|mut c| c.reset().map_err_trace_exit(1).map_info_str("Ok"))
},
Action::Set => {
let kv = String::from(name).into_kv();
if kv.is_none() {
warn!("Not a key-value pair: '{}'", name);
exit(1);
}
let (key, value) = kv.unwrap().into();
let value = FromStr::from_str(&value[..]);
if value.is_err() {
warn!("Not a integer: '{:?}'", value);
exit(1);
}
let value : i64 = value.unwrap();
Counter::load(String::from(key), rt.store())
.map(|mut c| c.set(value).map_err_trace_exit(1).map_info_str("Ok"))
},
}
.map_err_trace()
.ok();
},
|name| {
debug!("Call: {}", name);
match name {
"create" => create(&rt),
"delete" => delete(&rt),
"interactive" => interactive(&rt),
"list" => list(&rt),
_ => {
debug!("Unknown command"); // More error handling
},
};
})
}

View file

@ -1,139 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use clap::{Arg, App, SubCommand};
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
.arg(Arg::with_name("increment")
.long("inc")
.short("i")
.takes_value(true)
.required(false)
.help("Increment a counter")
.value_name("COUNTER"))
.arg(Arg::with_name("decrement")
.long("dec")
.short("d")
.takes_value(true)
.required(false)
.help("Decrement a counter")
.value_name("COUNTER"))
.arg(Arg::with_name("reset")
.long("reset")
.takes_value(true)
.required(false)
.help("Reset a counter")
.value_name("COUNTER"))
.arg(Arg::with_name("set")
.long("set")
.takes_value(true)
.required(false)
.help("Set a counter")
.value_name("COUNTER"))
.subcommand(SubCommand::with_name("create")
.about("Create a counter")
.version("0.1")
.arg(Arg::with_name("name")
.long("name")
.short("n")
.takes_value(true)
.required(true)
.help("Create counter with this name")
.value_name("NAME"))
.arg(Arg::with_name("initval")
.long("init")
.short("i")
.takes_value(true)
.required(false)
.help("Initial value")
.value_name("VALUE"))
.arg(Arg::with_name("unit")
.long("unit")
.short("u")
.takes_value(true)
.required(false)
.help("measurement unit")
.value_name("UNIT")))
.subcommand(SubCommand::with_name("delete")
.about("Delete a counter")
.version("0.1")
.arg(Arg::with_name("name")
.long("name")
.short("n")
.takes_value(true)
.required(true)
.help("Create counter with this name")
.value_name("NAME")))
.subcommand(SubCommand::with_name("list")
.about("List counters")
.version("0.1")
.arg(Arg::with_name("name")
.long("name")
.short("n")
.takes_value(true)
.required(false)
.help("List counters with this name (foo/bar and baz/bar would match 'bar')")
.value_name("NAME"))
.arg(Arg::with_name("greater-than")
.long("greater")
.short("g")
.takes_value(true)
.required(false)
.help("List counters which are greater than VALUE")
.value_name("VALUE"))
.arg(Arg::with_name("lower-than")
.long("lower")
.short("l")
.takes_value(true)
.required(false)
.help("List counters which are lower than VALUE")
.value_name("VALUE"))
.arg(Arg::with_name("equals")
.long("equal")
.short("e")
.takes_value(true)
.required(false)
.help("List counters which equal VALUE")
.value_name("VALUE"))
)
.subcommand(SubCommand::with_name("interactive")
.about("Interactively count things")
.version("0.1")
.arg(Arg::with_name("spec")
.long("spec")
.short("s")
.takes_value(true)
.multiple(true)
.required(true)
.help("Specification for key-bindings. Use <KEY>=<VALUE> where KEY is the
key to bind (single character) and VALUE is the path to the counter to bind
to.")
.value_name("KEY=VALUE")))
}

View file

@ -1,4 +0,0 @@
## libimagcounter
Library of "imag-counter", usable by other modules as well to implement counter
functionality for entries.

View file

@ -18,6 +18,9 @@ Version 0.y.z and thus we can break the API like we want and need to.
This section contains the changelog from the last release to the next release. This section contains the changelog from the last release to the next release.
* Major changes
* `imag-counter` and `libimagcounter` was removed.
## 0.4.0 ## 0.4.0
* Major changes * Major changes

View file

@ -84,11 +84,6 @@ destinations = [ "-" ]
level = "debug" level = "debug"
enabled = true enabled = true
[imag.logging.modules.libimagcounter]
destinations = [ "-" ]
level = "debug"
enabled = true
[imag.logging.modules.libimagdiary] [imag.logging.modules.libimagdiary]
destinations = [ "-" ] destinations = [ "-" ]
level = "debug" level = "debug"

View file

@ -1,23 +0,0 @@
[package]
name = "libimagcounter"
version = "0.5.0"
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
description = "Library for the imag core distribution"
keywords = ["imag", "PIM", "personal", "information", "management"]
readme = "../../../README.md"
license = "LGPL-2.1"
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
repository = "https://github.com/matthiasbeyer/imag"
homepage = "http://imag-pim.org"
[dependencies]
log = "0.3"
toml = "0.4"
toml-query = "^0.3.1"
error-chain = "0.10"
libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" }

View file

@ -1 +0,0 @@
../../../doc/src/05100-lib-counter.md

View file

@ -1,267 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::ops::DerefMut;
use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::set::TomlValueSetExt;
use std::collections::BTreeMap;
use std::fmt;
use std::fmt::Display;
use libimagstore::store::Store;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
use module_path::ModuleEntryPath;
use error::Result;
use error::CounterError as CE;
use error::CounterErrorKind as CEK;
use error::ResultExt;
pub type CounterName = String;
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct CounterUnit(String);
impl Display for CounterUnit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({})", self.0)
}
}
impl CounterUnit {
pub fn new<S: Into<String>>(unit: S) -> CounterUnit {
CounterUnit(unit.into())
}
}
pub struct Counter<'a> {
fle: FileLockEntry<'a>,
unit: Option<CounterUnit>,
}
impl<'a> Counter<'a> {
pub fn new(store: &Store, name: CounterName, init: i64) -> Result<Counter> {
use std::ops::DerefMut;
debug!("Creating new counter: '{}' with value: {}", name, init);
let fle = {
let id = try!(ModuleEntryPath::new(name.clone())
.into_storeid()
.chain_err(|| CEK::StoreWriteError));
let mut lockentry = try!(store.create(id).chain_err(|| CEK::StoreWriteError));
{
let entry = lockentry.deref_mut();
let header = entry.get_header_mut();
let setres = header.set(&String::from("counter"), Value::Table(BTreeMap::new()));
if setres.is_err() {
return Err(CE::from_kind(CEK::StoreWriteError));
}
let setres = header.set(&String::from("counter.name"), Value::String(name));
if setres.is_err() {
return Err(CE::from_kind(CEK::StoreWriteError))
}
let setres = header.set(&String::from("counter.value"), Value::Integer(init));
if setres.is_err() {
return Err(CE::from_kind(CEK::StoreWriteError))
}
}
lockentry
};
Ok(Counter { fle: fle, unit: None })
}
pub fn with_unit(mut self, unit: Option<CounterUnit>) -> Result<Counter<'a>> {
self.unit = unit;
if let Some(u) = self.unit.clone() {
let header = self.fle.deref_mut().get_header_mut();
let setres = header.set(&String::from("counter.unit"), Value::String(u.0));
if setres.is_err() {
self.unit = None;
return Err(CE::from_kind(CEK::StoreWriteError))
}
};
Ok(self)
}
pub fn inc(&mut self) -> Result<()> {
let header = self.fle.deref_mut().get_header_mut();
let query = String::from("counter.value");
match try!(header.read(&query).chain_err(|| CEK::StoreReadError)) {
Some(&Value::Integer(i)) => {
header.set(&query, Value::Integer(i + 1))
.chain_err(|| CEK::StoreWriteError)
.map(|_| ())
},
_ => Err(CE::from_kind(CEK::StoreReadError)),
}
}
pub fn dec(&mut self) -> Result<()> {
let header = self.fle.deref_mut().get_header_mut();
let query = String::from("counter.value");
match try!(header.read(&query).chain_err(|| CEK::StoreReadError)) {
Some(&Value::Integer(i)) => {
header.set(&query, Value::Integer(i - 1))
.chain_err(|| CEK::StoreWriteError)
.map(|_| ())
},
_ => Err(CE::from_kind(CEK::StoreReadError)),
}
}
pub fn reset(&mut self) -> Result<()> {
self.set(0)
}
pub fn set(&mut self, v: i64) -> Result<()> {
self.fle
.deref_mut()
.get_header_mut()
.set(&String::from("counter.value"), Value::Integer(v))
.chain_err(|| CEK::StoreWriteError)
.map(|_| ())
}
pub fn name(&self) -> Result<CounterName> {
self.read_header_at("counter.name", |v| match v {
Some(&Value::String(ref s)) => Ok(s.clone()),
Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)),
_ => Err(CE::from_kind(CEK::StoreReadError)),
})
}
pub fn value(&self) -> Result<i64> {
self.read_header_at("counter.value", |v| match v {
Some(&Value::Integer(i)) => Ok(i),
Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)),
_ => Err(CE::from_kind(CEK::StoreReadError)),
})
}
pub fn unit(&self) -> Option<&CounterUnit> {
self.unit.as_ref()
}
pub fn read_unit(&self) -> Result<Option<CounterUnit>> {
self.read_header_at("counter.unit", |s| match s {
Some(&Value::String(ref s)) => Ok(Some(CounterUnit::new(s.clone()))),
Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)),
_ => Err(CE::from_kind(CEK::StoreReadError)),
})
}
fn read_header_at<T, F>(&self, name: &str, f: F) -> Result<T>
where F: FnOnce(Option<&Value>) -> Result<T>
{
self.fle
.get_header()
.read(&String::from(name))
.chain_err(|| CEK::StoreWriteError)
.and_then(f)
}
pub fn load(name: CounterName, store: &Store) -> Result<Counter> {
debug!("Loading counter: '{}'", name);
let id = try!(ModuleEntryPath::new(name)
.into_storeid()
.chain_err(|| CEK::StoreWriteError));
Counter::from_storeid(store, id)
}
pub fn delete(name: CounterName, store: &Store) -> Result<()> {
debug!("Deleting counter: '{}'", name);
let id = try!(ModuleEntryPath::new(name)
.into_storeid()
.chain_err(|| CEK::StoreWriteError));
store.delete(id).chain_err(|| CEK::StoreWriteError)
}
pub fn all_counters(store: &Store) -> Result<CounterIterator> {
store.retrieve_for_module("counter")
.map(|iter| CounterIterator::new(store, iter))
.chain_err(|| CEK::StoreReadError)
}
}
trait FromStoreId {
fn from_storeid(&Store, StoreId) -> Result<Counter>;
}
impl<'a> FromStoreId for Counter<'a> {
fn from_storeid(store: &Store, id: StoreId) -> Result<Counter> {
debug!("Loading counter from storeid: '{:?}'", id);
match store.retrieve(id) {
Err(e) => Err(e).chain_err(|| CEK::StoreReadError),
Ok(c) => {
let mut counter = Counter { fle: c, unit: None };
counter.read_unit()
.chain_err(|| CEK::StoreReadError)
.and_then(|u| {
counter.unit = u;
Ok(counter)
})
}
}
}
}
pub struct CounterIterator<'a> {
store: &'a Store,
iditer: StoreIdIterator,
}
impl<'a> CounterIterator<'a> {
pub fn new(store: &'a Store, iditer: StoreIdIterator) -> CounterIterator<'a> {
CounterIterator {
store: store,
iditer: iditer,
}
}
}
impl<'a> Iterator for CounterIterator<'a> {
type Item = Result<Counter<'a>>;
fn next(&mut self) -> Option<Result<Counter<'a>>> {
self.iditer
.next()
.map(|id| Counter::from_storeid(self.store, id))
}
}

View file

@ -1,53 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
error_chain! {
types {
CounterError, CounterErrorKind, ResultExt, Result;
}
errors {
StoreIdError {
description("StoreId error")
display("StoreId error")
}
StoreReadError {
description("Store read error")
display("Store read error")
}
StoreWriteError {
description("Store write error")
display("Store write error")
}
HeaderTypeError {
description("Header type error")
display("Header type error")
}
HeaderFieldMissingError {
description("Header field missing error")
display("Header field missing error")
}
}
}

View file

@ -1,50 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#![recursion_limit="256"]
#![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 toml;
extern crate toml_query;
#[macro_use] extern crate log;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate libimagstore;
extern crate libimagerror;
module_entry_path_mod!("counter");
pub mod counter;
pub mod error;