1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::path::Path;
use std::path::PathBuf;
use std::result::Result as RResult;
use vobject::parse_component;
use libimagstore::store::Store;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreIdIterator;
use libimagentryref::refstore::RefStore;
use libimagentryref::refstore::UniqueRefPathGenerator;
use libimagentryutil::isa::Is;
use contact::IsContact;
use error::ContactError as CE;
use error::ContactErrorKind as CEK;
use error::Result;
use util;
pub struct UniqueContactPathGenerator;
impl UniqueRefPathGenerator for UniqueContactPathGenerator {
type Error = CE;
fn collection() -> &'static str {
"contact"
}
fn unique_hash<A: AsRef<Path>>(path: A) -> RResult<String, Self::Error> {
use vobject::vcard::Vcard;
debug!("Generating unique hash for path: {:?}", path.as_ref());
util::read_to_string(path.as_ref())
.and_then(|s| Vcard::build(&s).map_err(CE::from))
.and_then(|card| {
card.uid()
.map(|u| u.raw().clone())
.ok_or_else(|| {
let s = path.as_ref().to_str().unwrap_or("Unknown path");
CEK::UidMissing(String::from(s)).into()
})
})
}
}
pub trait ContactStore<'a> : RefStore<'a> {
fn create_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>>;
fn create_from_buf<P: AsRef<Path>>(&'a self, p: P, buf: &String) -> Result<FileLockEntry<'a>>;
fn all_contacts(&'a self) -> Result<StoreIdIterator>;
}
impl<'a> ContactStore<'a> for Store {
fn create_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>> {
util::read_to_string(p).and_then(|buf| self.create_from_buf(p, &buf))
}
fn create_from_buf<P: AsRef<Path>>(&'a self, p: P, buf: &String) -> Result<FileLockEntry<'a>> {
let component = parse_component(&buf)?;
debug!("Parsed: {:?}", component);
RefStore::create_ref::<UniqueContactPathGenerator, P>(self, p)
.map_err(From::from)
.and_then(|mut entry| {
entry.set_isflag::<IsContact>()
.map_err(From::from)
.map(|_| entry)
})
}
fn all_contacts(&'a self) -> Result<StoreIdIterator> {
let iter = self
.entries()?
.without_store()
.filter(|id| id.is_in_collection(&["contact"]));
Ok(StoreIdIterator::new(Box::new(iter)))
}
}