sqlite_collections/ds/set/
iter.rs

1use super::Error;
2use crate::format::Format;
3use crate::{identifier::Identifier, AsConnection};
4use rusqlite::{params, OptionalExtension};
5
6use std::marker::PhantomData;
7
8#[derive(Debug)]
9pub struct Iter<'db, 'tbl, S, C>
10where
11    S: Format,
12    C: AsConnection,
13{
14    connection: C,
15    database: Identifier<'db>,
16    table: Identifier<'tbl>,
17    front: Option<S::Buffer>,
18    back: Option<S::Buffer>,
19    size: usize,
20    serializer: PhantomData<S>,
21}
22
23impl<'db, 'tbl, S, C> Iter<'db, 'tbl, S, C>
24where
25    S: Format,
26    C: AsConnection,
27{
28    pub fn new(
29        connection: C,
30        database: Identifier<'db>,
31        table: Identifier<'tbl>,
32    ) -> rusqlite::Result<Self> {
33        let mut new = Self {
34            connection,
35            database,
36            table,
37            size: 0,
38            front: None,
39            back: None,
40            serializer: PhantomData,
41        };
42        new.update_size()?;
43        Ok(new)
44    }
45
46    fn update_size(&mut self) -> rusqlite::Result<usize> {
47        self.size = self.select("COUNT(*)", "", |row| row.get(0))?;
48        Ok(self.size)
49    }
50
51    fn select<U, F>(&self, selection: &str, order: &str, f: F) -> rusqlite::Result<U>
52    where
53        F: FnOnce(&rusqlite::Row<'_>) -> rusqlite::Result<U>,
54    {
55        let database = &self.database;
56        let table = &self.table;
57
58        match (
59            self.front.as_ref(),
60            self.back.as_ref(),
61        ) {
62            (None, None) => self
63                .connection
64                .as_connection()
65                .prepare_cached(&format!(
66                    "SELECT {selection} FROM {database}.{table} {order} LIMIT 1"
67                ))?
68                .query_row([], f),
69            (Some(front), None) => self
70                .connection
71                .as_connection()
72                .prepare_cached(&format!(
73                    "SELECT {selection} FROM {database}.{table} WHERE key > ? {order} LIMIT 1"
74                ))?
75                .query_row(params![front], f),
76            (None, Some(back)) => self
77                .connection
78                .as_connection()
79                .prepare_cached(&format!(
80                    "SELECT {selection} FROM {database}.{table} WHERE key < ? {order} LIMIT 1"
81                ))?
82                .query_row(params![back], f),
83            (Some(front), Some(back)) => self
84                .connection
85                .as_connection()
86                .prepare_cached(&format!(
87                    "SELECT {selection} FROM {database}.{table} WHERE key > ? AND key < ? {order} LIMIT 1"
88                ))?
89                .query_row(params![front, back], f),
90        }
91    }
92}
93
94impl<'db, 'tbl, S, C> Iterator for Iter<'db, 'tbl, S, C>
95where
96    S: Format,
97    C: AsConnection,
98{
99    type Item = Result<S::Out, Error<S>>;
100
101    fn next(&mut self) -> Option<Self::Item> {
102        let next: rusqlite::Result<Option<S::Buffer>> = self
103            .select("key", "ORDER BY key ASC", |row| row.get(0))
104            .optional();
105        match next {
106            Ok(Some(serialized)) => {
107                let ret = S::deserialize(&serialized).map_err(Error::Deserialize);
108                self.front = Some(serialized);
109                Some(self.update_size().map_err(Into::into).and(ret))
110            }
111            Ok(None) => {
112                self.size = 0;
113                None
114            }
115            Err(e) => Some(Err(e.into())),
116        }
117    }
118
119    /// return how many elements are in left in the iterator as of this call.
120    /// This can change during iteration if you are iterating in autocommit
121    /// mode, or hold the iterator across transactions. This is why this
122    /// iterator doesn't implement ExactSizeIterator
123    fn size_hint(&self) -> (usize, Option<usize>) {
124        (self.size, Some(self.size))
125    }
126}
127
128impl<'db, 'tbl, S, C> DoubleEndedIterator for Iter<'db, 'tbl, S, C>
129where
130    S: Format,
131    C: AsConnection,
132{
133    fn next_back(&mut self) -> Option<Self::Item> {
134        let next: rusqlite::Result<Option<S::Buffer>> = self
135            .select("key", "ORDER BY key DESC", |row| row.get(0))
136            .optional();
137        match next {
138            Ok(Some(serialized)) => {
139                let ret = S::deserialize(&serialized).map_err(Error::Deserialize);
140                self.back = Some(serialized);
141                Some(self.update_size().map_err(Into::into).and(ret))
142            }
143            Ok(None) => {
144                self.size = 0;
145                None
146            }
147            Err(e) => Some(Err(e.into())),
148        }
149    }
150}