1use std::collections::HashMap;
2use std::convert::TryFrom;
3use std::ops::{Deref, Index};
4use std::rc::Rc;
5
6use crate::columns::Bindable;
7use crate::error::{Error, Result};
8use crate::statement::{State, Statement};
9use crate::value::Value;
10
11pub struct Cursor<'m> {
13 column_count: usize,
14 statement: &'m Statement,
15 poisoned: bool,
16}
17
18#[derive(Debug)]
29pub struct Row {
30 column_names: Rc<Vec<String>>,
31 column_mapping: Rc<HashMap<String, usize>>,
32 values: Vec<Value>,
33}
34
35pub trait RowIndex: std::fmt::Debug + std::fmt::Display {
37 fn contains(&self, row: &Row) -> bool;
39
40 fn index(self, row: &Row) -> usize;
44}
45
46macro_rules! implement(
47 ($type:ident<$($lifetime:lifetime),+>) => {
48 impl<$($lifetime),+> $type<$($lifetime),+> {
49 pub fn bind<T: Bindable>(self, value: T) -> Result<Self> {
54 #[allow(unused_mut)]
55 let mut cursor = self.reset()?;
56 cursor.statement.bind(value)?;
57 Ok(cursor)
58 }
59
60 #[allow(unused_mut)]
64 pub fn bind_iter<T, U>(self, value: T) -> Result<Self>
65 where
66 T: IntoIterator<Item = U>,
67 U: Bindable,
68 {
69 let mut cursor = self.reset()?;
70 cursor.statement.bind_iter(value)?;
71 Ok(cursor)
72 }
73
74 #[allow(unused_mut)]
76 pub fn reset(mut self) -> Result<Self> {
77 self.statement.reset()?;
78 self.poisoned = false;
79 Ok(self)
80 }
81
82 pub fn try_next(&mut self) -> Result<Option<Vec<Value>>> {
84 if self.statement.next()? == State::Done {
85 return Ok(None);
86 }
87 let mut values = Vec::with_capacity(self.column_count);
88 for index in 0..self.column_count {
89 values.push(self.statement.read(index)?);
90 }
91 Ok(Some(values))
92 }
93 }
94
95 impl<$($lifetime),+> Deref for $type<$($lifetime),+> {
96 type Target = Statement;
97
98 #[inline]
99 fn deref(&self) -> &Self::Target {
100 &self.statement
101 }
102 }
103
104 impl<$($lifetime),+> Iterator for $type<$($lifetime),+> {
105 type Item = Result<Row>;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 if self.poisoned {
109 return None;
110 }
111 match self.try_next() {
112 Ok(value) => {
113 value.map(|values| Ok(Row {
114 column_names: self.statement.column_names.clone(),
115 column_mapping: self.statement.column_mapping(),
116 values,
117 }))
118 }
119 Err(error) => {
120 self.poisoned = true;
121 Some(Err(error))
122 }
123 }
124 }
125 }
126 }
127);
128
129implement!(Cursor<'m>);
130impl Row {
142 #[inline]
146 pub fn contains<T>(&self, column: T) -> bool
147 where
148 T: RowIndex,
149 {
150 column.contains(self)
151 }
152
153 #[inline]
161 pub fn read<'l, T, U>(&'l self, column: U) -> T
162 where
163 T: TryFrom<&'l Value, Error = Error>,
164 U: RowIndex,
165 {
166 self.try_read(column).unwrap()
167 }
168
169 #[inline]
174 pub fn take<U>(&mut self, column: U) -> Value
175 where
176 U: RowIndex,
177 {
178 let index = column.index(self);
179 std::mem::take(&mut self.values[index])
180 }
181
182 #[inline]
186 pub fn try_read<'l, T, U>(&'l self, column: U) -> Result<T>
187 where
188 T: TryFrom<&'l Value, Error = Error>,
189 U: RowIndex,
190 {
191 if !column.contains(self) {
192 raise!("the index is out of range ({column})");
193 }
194 T::try_from(&self.values[column.index(self)])
195 }
196
197 pub fn iter(&self) -> impl Iterator<Item = (&'_ str, &'_ Value)> + use<'_> {
199 self.column_names.iter().map(|column_name| {
200 (
201 column_name.as_str(),
202 &self.values[self.column_mapping[column_name]],
203 )
204 })
205 }
206}
207
208impl From<Row> for Vec<Value> {
209 #[inline]
210 fn from(row: Row) -> Self {
211 row.values
212 }
213}
214
215impl<T> Index<T> for Row
216where
217 T: RowIndex,
218{
219 type Output = Value;
220
221 fn index(&self, index: T) -> &Value {
222 &self.values[index.index(self)]
223 }
224}
225
226impl RowIndex for &str {
227 #[inline]
228 fn contains(&self, row: &Row) -> bool {
229 row.column_mapping.contains_key(*self)
230 }
231
232 #[inline]
233 fn index(self, row: &Row) -> usize {
234 debug_assert!(RowIndex::contains(&self, row), "the index is out of range");
235 row.column_mapping[self]
236 }
237}
238
239impl RowIndex for usize {
240 #[inline]
241 fn contains(&self, row: &Row) -> bool {
242 self < &row.values.len()
243 }
244
245 #[inline]
246 fn index(self, row: &Row) -> usize {
247 debug_assert!(RowIndex::contains(&self, row), "the index is out of range");
248 self
249 }
250}
251
252pub fn new<'m>(statement: &'m Statement) -> Cursor<'m> {
253 Cursor {
254 column_count: statement.column_count(),
255 statement,
256 poisoned: false,
257 }
258}
259
260