A file-based task manager
1use std::collections::BTreeMap;
2use std::collections::btree_map::Entry;
3use std::collections::btree_map::{IntoIter as BTreeIntoIter, Iter as BTreeMapIter};
4use std::iter::Chain;
5
6type Map = BTreeMap<String, String>;
7
8#[allow(dead_code)]
9/// Holds xattributes in a way that allows for differentiating between attributes that have been
10/// added/modified or that were present when reading the file. This is an *optimization* over
11/// infrequently modified values.
12#[derive(Default, Clone, Debug)]
13pub(crate) struct Attrs {
14 pub written: Map,
15 pub updated: Map,
16}
17
18impl IntoIterator for Attrs {
19 type Item = (String, String);
20
21 type IntoIter = Chain<BTreeIntoIter<String, String>, BTreeIntoIter<String, String>>;
22
23 fn into_iter(self) -> Self::IntoIter {
24 self.written.into_iter().chain(self.updated)
25 }
26}
27
28#[allow(dead_code)]
29impl Attrs {
30 pub(crate) fn from_written(written: Map) -> Self {
31 Self {
32 written,
33 ..Default::default()
34 }
35 }
36
37 pub(crate) fn get(&self, key: &str) -> Option<&String> {
38 self.updated.get(key).or_else(|| self.written.get(key))
39 }
40
41 pub(crate) fn insert(&mut self, key: String, value: String) -> Option<String> {
42 match self.updated.entry(key.clone()) {
43 Entry::Occupied(mut e) => Some(e.insert(value)),
44 Entry::Vacant(e) => {
45 e.insert(value);
46 let maybe_old_value = self.written.get(&key);
47 maybe_old_value.cloned()
48 }
49 }
50 }
51
52 pub(crate) fn is_empty(&self) -> bool {
53 self.updated.is_empty() && self.written.is_empty()
54 }
55
56 pub(crate) fn iter(
57 &self,
58 ) -> Chain<BTreeMapIter<'_, String, String>, BTreeMapIter<'_, String, String>> {
59 self.written.iter().chain(self.updated.iter())
60 }
61}