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
use crate::{
    index::{
        config::{IndexType, IndexTypeUnwrap},
        raw_iter::IndexRawIter,
        raw_iter_tx::TxIndexRawIter,
    },
    persy::PersyImpl,
    Transaction, ValueIter,
};
use std::sync::Arc;

/// Index Iterator implementation for iterating on a range of keys
///
/// Example
/// ```rust
/// # use persy::{OpenOptions,ValueMode, IndexIter};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let persy = OpenOptions::new().memory()?;
/// # let mut tx = persy.begin()?;
/// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
/// # tx.put::<u8,u8>("my_new_index",10,10)?;
/// # let prepared = tx.prepare()?;
/// # prepared.commit()?;
/// let iter:IndexIter<u8,u8> = persy.range("my_new_index",10..12)?;
/// for (k,values) in iter  {
///     for value in values {
///         //...
///     }
/// }
/// # Ok(())
/// # }
/// ```
pub struct IndexIter<K: IndexType, V: IndexType> {
    iter_impl: IndexRawIter<K::Wrapper, V::Wrapper>,
    persy_impl: Arc<PersyImpl>,
}

impl<K: IndexType, V: IndexType> IndexIter<K, V> {
    pub(crate) fn new(iter_impl: IndexRawIter<K::Wrapper, V::Wrapper>, persy_impl: Arc<PersyImpl>) -> IndexIter<K, V> {
        IndexIter { iter_impl, persy_impl }
    }
}

impl<K, V> Iterator for IndexIter<K, V>
where
    K: IndexType,
    V: IndexType,
{
    type Item = (K, ValueIter<V>);

    fn next(&mut self) -> Option<Self::Item> {
        self.iter_impl
            .next(&self.persy_impl)
            .map(|(k, v)| (k.unwrap(), ValueIter::from(v)))
    }
}
impl<K, V> DoubleEndedIterator for IndexIter<K, V>
where
    K: IndexType,
    V: IndexType,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter_impl
            .next_back(&self.persy_impl)
            .map(|(k, v)| (k.unwrap(), ValueIter::from(v)))
    }
}

/// Index Iterator implementation for iterating on a range of keys
/// considering changes in transaction
///
/// # Example
///
/// ```rust
/// # use persy::{OpenOptions, ValueMode, TxIndexIter};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let persy = OpenOptions::new().memory()?;
/// let mut tx = persy.begin()?;
/// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
/// tx.put::<u8,u8>("my_new_index",10,10)?;
/// {
///     let iter:TxIndexIter<u8,u8> = tx.range("my_new_index",10..12)?;
///     for (k,values) in iter  {
///         for value in values {
///             //...
///         }
///     }
/// }
/// tx.prepare()?.commit()?;
/// # Ok(())
/// # }
/// ```
pub struct TxIndexIter<'a, K: IndexType, V: IndexType> {
    iter_impl: TxIndexRawIter<K::Wrapper, V::Wrapper>,
    tx: &'a mut Transaction,
}

impl<'a, K: IndexType, V: IndexType> TxIndexIter<'a, K, V> {
    pub(crate) fn new(
        iter_impl: TxIndexRawIter<K::Wrapper, V::Wrapper>,
        tx: &'a mut Transaction,
    ) -> TxIndexIter<'a, K, V> {
        TxIndexIter { iter_impl, tx }
    }

    /// get the next element in the iterator giving the access on the transaction owned by the
    /// iterator
    pub fn next_tx(&mut self) -> Option<(K, ValueIter<V>, &mut Transaction)> {
        if let Some((k, v)) = self.iter_impl.next(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap()) {
            Some((k.unwrap(), ValueIter::from(v), self.tx))
        } else {
            None
        }
    }

    /// Direct access to the transaction owned by the iterator
    pub fn tx(&mut self) -> &mut Transaction {
        self.tx
    }
}

impl<'a, K, V> Iterator for TxIndexIter<'a, K, V>
where
    K: IndexType,
    V: IndexType,
{
    type Item = (K, ValueIter<V>);

    fn next(&mut self) -> Option<Self::Item> {
        self.iter_impl
            .next(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap())
            .map(|(k, v)| (k.unwrap(), ValueIter::from(v)))
    }
}

impl<'a, K, V> DoubleEndedIterator for TxIndexIter<'a, K, V>
where
    K: IndexType,
    V: IndexType,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter_impl
            .next_back(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap())
            .map(|(k, v)| (k.unwrap(), ValueIter::from(v)))
    }
}