sqlite_collections/ds/map/iter/
value.rs1use crate::ds::map::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, K, V, C>
10where
11 K: Format,
12 V: Format,
13 C: AsConnection,
14{
15 connection: C,
16 database: Identifier<'db>,
17 table: Identifier<'tbl>,
18 front: Option<K::Buffer>,
19 back: Option<K::Buffer>,
20 size: usize,
21 key_serializer: PhantomData<K>,
22 value_serializer: PhantomData<V>,
23}
24
25impl<'db, 'tbl, K, V, C> Iter<'db, 'tbl, K, V, C>
26where
27 K: Format,
28 V: Format,
29 C: AsConnection,
30{
31 pub fn new(
32 connection: C,
33 database: Identifier<'db>,
34 table: Identifier<'tbl>,
35 ) -> rusqlite::Result<Self> {
36 let mut new = Self {
37 connection,
38 database,
39 table,
40 size: 0,
41 front: None,
42 back: None,
43 key_serializer: PhantomData,
44 value_serializer: PhantomData,
45 };
46 new.update_size()?;
47 Ok(new)
48 }
49
50 fn update_size(&mut self) -> rusqlite::Result<usize> {
51 self.size = self.select("COUNT(*)", "", |row| row.get(0))?;
52 Ok(self.size)
53 }
54
55 fn select<U, F>(&self, selection: &str, order: &str, f: F) -> rusqlite::Result<U>
56 where
57 F: FnOnce(&rusqlite::Row<'_>) -> rusqlite::Result<U>,
58 {
59 let database = &self.database;
60 let table = &self.table;
61
62 match (self.front.as_ref(), self.back.as_ref()) {
63 (None, None) => self
64 .connection
65 .as_connection()
66 .prepare_cached(&format!(
67 "SELECT {selection} FROM {database}.{table} {order} LIMIT 1"
68 ))?
69 .query_row([], f),
70 (Some(front), None) => self
71 .connection
72 .as_connection()
73 .prepare_cached(&format!(
74 "SELECT {selection} FROM {database}.{table} WHERE key > ? {order} LIMIT 1"
75 ))?
76 .query_row(params![front], f),
77 (None, Some(back)) => self
78 .connection
79 .as_connection()
80 .prepare_cached(&format!(
81 "SELECT {selection} FROM {database}.{table} WHERE key < ? {order} LIMIT 1"
82 ))?
83 .query_row(params![back], f),
84 (Some(front), Some(back)) => self
85 .connection
86 .as_connection()
87 .prepare_cached(&format!(
88 "SELECT {selection} FROM {database}.{table} WHERE key > ? AND key < ? {order} LIMIT 1"
89 ))?
90 .query_row(params![front, back], f),
91 }
92 }
93}
94
95impl<'db, 'tbl, K, V, C> Iterator for Iter<'db, 'tbl, K, V, C>
96where
97 K: Format,
98 V: Format,
99 C: AsConnection,
100{
101 type Item = Result<V::Out, Error<K, V>>;
102
103 fn next(&mut self) -> Option<Self::Item> {
104 let next: rusqlite::Result<Option<(K::Buffer, V::Buffer)>> = self
105 .select("key, value", "ORDER BY key ASC", |row| {
106 Ok((row.get(0)?, row.get(1)?))
107 })
108 .optional();
109 match next {
110 Ok(Some((key, value))) => {
111 let ret = V::deserialize(&value).map_err(Error::ValueDeserialize);
112 self.front = Some(key);
113 Some(self.update_size().map_err(Into::into).and(ret))
114 }
115 Ok(None) => {
116 self.size = 0;
117 None
118 }
119 Err(e) => Some(Err(e.into())),
120 }
121 }
122
123 fn size_hint(&self) -> (usize, Option<usize>) {
128 (self.size, Some(self.size))
129 }
130}
131
132impl<'db, 'tbl, K, V, C> DoubleEndedIterator for Iter<'db, 'tbl, K, V, C>
133where
134 K: Format,
135 V: Format,
136 C: AsConnection,
137{
138 fn next_back(&mut self) -> Option<Self::Item> {
139 let next: rusqlite::Result<Option<(K::Buffer, V::Buffer)>> = self
140 .select("key, value", "ORDER BY key DESC", |row| {
141 Ok((row.get(0)?, row.get(1)?))
142 })
143 .optional();
144 match next {
145 Ok(Some((key, value))) => {
146 let ret = V::deserialize(&value).map_err(Error::ValueDeserialize);
147 self.back = Some(key);
148 Some(self.update_size().map_err(Into::into).and(ret))
149 }
150 Ok(None) => {
151 self.size = 0;
152 None
153 }
154 Err(e) => Some(Err(e.into())),
155 }
156 }
157}