sqlite_collections/ds/map/iter/
key.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 (
63 self.front.as_ref(),
64 self.back.as_ref(),
65 ) {
66 (None, None) => self
67 .connection
68 .as_connection()
69 .prepare_cached(&format!(
70 "SELECT {selection} FROM {database}.{table} {order} LIMIT 1"
71 ))?
72 .query_row([], f),
73 (Some(front), None) => self
74 .connection
75 .as_connection()
76 .prepare_cached(&format!(
77 "SELECT {selection} FROM {database}.{table} WHERE key > ? {order} LIMIT 1"
78 ))?
79 .query_row(params![front], f),
80 (None, Some(back)) => self
81 .connection
82 .as_connection()
83 .prepare_cached(&format!(
84 "SELECT {selection} FROM {database}.{table} WHERE key < ? {order} LIMIT 1"
85 ))?
86 .query_row(params![back], f),
87 (Some(front), Some(back)) => self
88 .connection
89 .as_connection()
90 .prepare_cached(&format!(
91 "SELECT {selection} FROM {database}.{table} WHERE key > ? AND key < ? {order} LIMIT 1"
92 ))?
93 .query_row(params![front, back], f),
94 }
95 }
96}
97
98impl<'db, 'tbl, K, V, C> Iterator for Iter<'db, 'tbl, K, V, C>
99where
100 K: Format,
101 V: Format,
102 C: AsConnection,
103{
104 type Item = Result<K::Out, Error<K, V>>;
105
106 fn next(&mut self) -> Option<Self::Item> {
107 let next: rusqlite::Result<Option<K::Buffer>> = self
108 .select("key", "ORDER BY key ASC", |row| row.get(0))
109 .optional();
110 match next {
111 Ok(Some(serialized)) => {
112 let ret = K::deserialize(&serialized).map_err(Error::KeyDeserialize);
113 self.front = Some(serialized);
114 Some(self.update_size().map_err(Into::into).and(ret))
115 }
116 Ok(None) => {
117 self.size = 0;
118 None
119 }
120 Err(e) => Some(Err(e.into())),
121 }
122 }
123
124 fn size_hint(&self) -> (usize, Option<usize>) {
129 (self.size, Some(self.size))
130 }
131}
132
133impl<'db, 'tbl, K, V, C> DoubleEndedIterator for Iter<'db, 'tbl, K, V, C>
134where
135 K: Format,
136 V: Format,
137 C: AsConnection,
138{
139 fn next_back(&mut self) -> Option<Self::Item> {
140 let next: rusqlite::Result<Option<K::Buffer>> = self
141 .select("key", "ORDER BY key DESC", |row| row.get(0))
142 .optional();
143 match next {
144 Ok(Some(serialized)) => {
145 let ret = K::deserialize(&serialized).map_err(Error::KeyDeserialize);
146 self.back = Some(serialized);
147 Some(self.update_size().map_err(Into::into).and(ret))
148 }
149 Ok(None) => {
150 self.size = 0;
151 None
152 }
153 Err(e) => Some(Err(e.into())),
154 }
155 }
156}