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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
use persy::PRes;
use persy::{IndexType, Persy, PersyError};
use std::{borrow::Cow, marker::PhantomData, ops::RangeBounds};

/// This type represents a key-..-value iterator
pub struct Iter<K, V>(pub(crate) persy::IndexIter<K, V>)
where
    K: IndexType,
    V: IndexType;

impl<K, V> Iterator for Iter<K, V>
where
    K: IndexType,
    V: IndexType,
{
    type Item = (K, persy::Value<V>);
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// This type represents a keys iterator
pub struct KeysIter<K, V>(
    pub(crate) std::iter::Map<persy::IndexIter<K, V>, fn((K, persy::Value<V>)) -> K>,
)
where
    K: IndexType,
    V: IndexType;

impl<K, V> Iterator for KeysIter<K, V>
where
    K: IndexType,
    V: IndexType,
{
    type Item = K;
    #[inline]
    fn next(&mut self) -> Option<K> {
        self.0.next()
    }
}

/// This trait represents the common interface for all key-...-value stores defined in this crate
pub trait KV<K, V>
where
    K: IndexType,
    V: IndexType,
{
    /// Removes all entries from the KV store
    fn clear(&self) -> PRes<()>;

    /// Inserts a key, value pair into the KV store
    fn insert(&self, key: K, value: V) -> PRes<()>;

    /// Gets all the keys contained in the KV store
    fn keys(&self) -> PRes<KeysIter<K, V>>;

    /// Removes a key and associated value from the KV store
    fn remove(&self, key: K) -> PRes<()>;
}

/// The type that represents a key--(value mode generic)-value store
pub struct BaseKV<K, V>(
    Persy,
    Cow<'static, str>,
    persy::ValueMode,
    PhantomData<(K, V)>,
);

impl<K, V> Clone for BaseKV<K, V> {
    fn clone(&self) -> Self {
        BaseKV(self.0.clone(), self.1.clone(), self.2.clone(), PhantomData)
    }
}

impl<K, V> BaseKV<K, V>
where
    K: IndexType,
    V: IndexType,
{
    /// Creates a new instance of the value-mode-generic KV store
    pub fn new(p: &str, idxn: impl Into<Cow<'static, str>>, vm: persy::ValueMode) -> PRes<Self> {
        Self::new_intern(p, idxn.into(), vm)
    }

    pub(crate) fn new_intern(p: &str, idxn: Cow<'static, str>, vm: persy::ValueMode) -> PRes<Self> {
        match Persy::create(p) {
            Ok(_) => {}
            Err(PersyError::Io(ref e)) if e.kind() == std::io::ErrorKind::AlreadyExists => {}
            Err(e) => return Err(e),
        }

        Self::with_backend_intern(Persy::open(p, persy::Config::new())?, idxn, vm)
    }

    /// Creates a new instance of the value-mode-generic KV store with the specified Persy instance as backend
    pub fn with_backend(
        persy: Persy,
        idxn: impl Into<Cow<'static, str>>,
        vm: persy::ValueMode,
    ) -> PRes<Self> {
        Self::with_backend_intern(persy, idxn.into(), vm)
    }

    pub(crate) fn with_backend_intern(
        persy: Persy,
        idxn: Cow<'static, str>,
        vm: persy::ValueMode,
    ) -> PRes<Self> {
        let ridxn = idxn.as_ref();

        if !persy.exists_index(ridxn)? {
            let mut tx = persy.begin()?;
            persy.create_index::<K, V>(&mut tx, ridxn, vm.clone())?;
            let prepared = persy.prepare_commit(tx)?;
            persy.commit(prepared)?;
        }

        Ok(BaseKV(persy, idxn, vm, PhantomData))
    }

    /// Gets the associated value from a key
    pub fn get(&self, key: &K) -> PRes<Option<persy::Value<V>>> {
        self.0.get::<K, V>(self.1.as_ref(), key)
    }

    /// Returns an iterator visiting all key-value pairs in arbitrary order
    #[inline]
    pub fn iter(&self) -> PRes<Iter<K, V>> {
        self.range(..)
    }

    /// Returns an iterator visiting all key-value pairs inside the specified range in arbitrary order
    pub fn range<R>(&self, r: R) -> PRes<Iter<K, V>>
    where
        R: RangeBounds<K>,
    {
        self.0.range::<K, V, _>(self.1.as_ref(), r).map(Iter)
    }
}

impl<K, V> KV<K, V> for BaseKV<K, V>
where
    K: IndexType,
    V: IndexType,
{
    /// Removes all entries from the KV store
    fn clear(&self) -> PRes<()> {
        let mut tx = self.0.begin()?;
        self.0.drop_index(&mut tx, self.1.as_ref())?;
        self.0
            .create_index::<K, V>(&mut tx, self.1.as_ref(), self.2.clone())?;
        let prepared = self.0.prepare_commit(tx)?;
        self.0.commit(prepared)
    }

    /// Inserts a key, value pair into the KV store
    fn insert(&self, key: K, value: V) -> PRes<()> {
        let mut tx = self.0.begin()?;
        self.0.put::<K, V>(&mut tx, self.1.as_ref(), key, value)?;
        let prepared = self.0.prepare_commit(tx)?;
        self.0.commit(prepared)
    }

    /// Gets all the keys contained in the KV store
    #[inline]
    fn keys(&self) -> PRes<KeysIter<K, V>> {
        fn first_of2<A, B>(x: (A, B)) -> A {
            x.0
        }

        Ok(KeysIter(self.range(..)?.0.map(first_of2)))
    }

    /// Removes a key and associated value from the KV store
    fn remove(&self, key: K) -> PRes<()> {
        let mut tx = self.0.begin()?;
        self.0.remove::<K, V>(&mut tx, self.1.as_ref(), key, None)?;
        let prepared = self.0.prepare_commit(tx)?;
        self.0.commit(prepared)
    }
}