noria/view/
results.rs

1use crate::data::*;
2use std::fmt;
3use std::ops::Deref;
4use std::sync::Arc;
5
6/// A result set from a Noria query.
7#[derive(PartialEq, Eq)]
8pub struct Results {
9    results: Vec<Vec<DataType>>,
10    columns: Arc<[String]>,
11}
12
13impl Results {
14    // NOTE: should be pub(crate), but that triggers:
15    // https://github.com/rust-lang/rust/issues/69785
16    #[doc(hidden)]
17    pub fn new(results: Vec<Vec<DataType>>, columns: Arc<[String]>) -> Self {
18        Self { results, columns }
19    }
20
21    /// Iterate over references to the returned rows.
22    pub fn iter(&self) -> ResultIter<'_> {
23        self.into_iter()
24    }
25}
26
27impl Into<Vec<Vec<DataType>>> for Results {
28    fn into(self) -> Vec<Vec<DataType>> {
29        self.results
30    }
31}
32
33impl PartialEq<[Vec<DataType>]> for Results {
34    fn eq(&self, other: &[Vec<DataType>]) -> bool {
35        self.results == other
36    }
37}
38
39impl PartialEq<Vec<Vec<DataType>>> for Results {
40    fn eq(&self, other: &Vec<Vec<DataType>>) -> bool {
41        &self.results == other
42    }
43}
44
45impl PartialEq<&'_ Vec<Vec<DataType>>> for Results {
46    fn eq(&self, other: &&Vec<Vec<DataType>>) -> bool {
47        &self.results == *other
48    }
49}
50
51/// A reference to a row in a result set.
52///
53/// You can access fields either by numerical index or by field index.
54/// If you want to also perform type conversion, use [`ResultRow::get`].
55#[derive(PartialEq, Eq)]
56pub struct ResultRow<'a> {
57    result: &'a Vec<DataType>,
58    columns: &'a [String],
59}
60
61impl<'a> ResultRow<'a> {
62    fn new(row: &'a Vec<DataType>, columns: &'a [String]) -> Self {
63        Self {
64            result: row,
65            columns,
66        }
67    }
68}
69
70impl std::ops::Index<usize> for ResultRow<'_> {
71    type Output = DataType;
72    fn index(&self, index: usize) -> &Self::Output {
73        &self.result[index]
74    }
75}
76
77impl std::ops::Index<&'_ str> for ResultRow<'_> {
78    type Output = DataType;
79    fn index(&self, index: &'_ str) -> &Self::Output {
80        let index = self.columns.iter().position(|col| col == index).unwrap();
81        &self.result[index]
82    }
83}
84
85impl<'a> ResultRow<'a> {
86    /// Retrieve the field of the result by the given name as a `T`.
87    ///
88    /// Returns `None` if the given field does not exist.
89    ///
90    /// Panics if the value at the given field cannot be turned into a `T`.
91    pub fn get<T>(&self, field: &str) -> Option<T>
92    where
93        &'a DataType: Into<T>,
94    {
95        let index = self.columns.iter().position(|col| col == field)?;
96        Some((&self.result[index]).into())
97    }
98}
99
100impl PartialEq<[DataType]> for ResultRow<'_> {
101    fn eq(&self, other: &[DataType]) -> bool {
102        &self.result[..] == other
103    }
104}
105
106impl PartialEq<Vec<DataType>> for ResultRow<'_> {
107    fn eq(&self, other: &Vec<DataType>) -> bool {
108        self.result == other
109    }
110}
111
112impl PartialEq<&'_ Vec<DataType>> for ResultRow<'_> {
113    fn eq(&self, other: &&Vec<DataType>) -> bool {
114        &self.result == other
115    }
116}
117
118impl fmt::Debug for ResultRow<'_> {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
120        f.debug_map()
121            .entries(self.columns.iter().zip(self.result.iter()))
122            .finish()
123    }
124}
125
126impl fmt::Debug for Results {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
128        f.debug_list()
129            .entries(self.results.iter().map(|r| ResultRow {
130                result: r,
131                columns: &self.columns,
132            }))
133            .finish()
134    }
135}
136
137impl Deref for Results {
138    type Target = [Vec<DataType>];
139    fn deref(&self) -> &Self::Target {
140        &self.results
141    }
142}
143
144impl AsRef<[Vec<DataType>]> for Results {
145    fn as_ref(&self) -> &[Vec<DataType>] {
146        &self.results
147    }
148}
149
150pub struct ResultIter<'a> {
151    results: std::slice::Iter<'a, Vec<DataType>>,
152    columns: &'a [String],
153}
154
155impl<'a> IntoIterator for &'a Results {
156    type Item = ResultRow<'a>;
157    type IntoIter = ResultIter<'a>;
158    fn into_iter(self) -> Self::IntoIter {
159        ResultIter {
160            results: self.results.iter(),
161            columns: &self.columns,
162        }
163    }
164}
165
166impl<'a> Iterator for ResultIter<'a> {
167    type Item = ResultRow<'a>;
168    fn next(&mut self) -> Option<Self::Item> {
169        Some(ResultRow::new(self.results.next()?, &self.columns))
170    }
171
172    fn size_hint(&self) -> (usize, Option<usize>) {
173        self.results.size_hint()
174    }
175}
176
177impl ExactSizeIterator for ResultIter<'_> {}
178impl DoubleEndedIterator for ResultIter<'_> {
179    fn next_back(&mut self) -> Option<Self::Item> {
180        Some(ResultRow::new(self.results.next_back()?, &self.columns))
181    }
182
183    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
184        Some(ResultRow::new(self.results.nth_back(n)?, &self.columns))
185    }
186}
187
188pub struct ResultIntoIter {
189    results: std::vec::IntoIter<Vec<DataType>>,
190    columns: Arc<[String]>,
191}
192
193impl IntoIterator for Results {
194    type Item = Row;
195    type IntoIter = ResultIntoIter;
196    fn into_iter(self) -> Self::IntoIter {
197        ResultIntoIter {
198            results: self.results.into_iter(),
199            columns: self.columns,
200        }
201    }
202}
203
204impl Iterator for ResultIntoIter {
205    type Item = Row;
206    fn next(&mut self) -> Option<Self::Item> {
207        Some(Row::new(self.results.next()?, &self.columns))
208    }
209
210    fn size_hint(&self) -> (usize, Option<usize>) {
211        self.results.size_hint()
212    }
213}
214
215impl ExactSizeIterator for ResultIntoIter {}
216impl DoubleEndedIterator for ResultIntoIter {
217    fn next_back(&mut self) -> Option<Self::Item> {
218        Some(Row::new(self.results.next_back()?, &self.columns))
219    }
220
221    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
222        Some(Row::new(self.results.nth_back(n)?, &self.columns))
223    }
224}
225
226/// A single row from a result set.
227///
228/// You can access fields either by numerical index or by field index.
229/// If you want to also perform type conversion, use [`Row::get`].
230#[derive(PartialEq, Eq)]
231pub struct Row {
232    row: Vec<DataType>,
233    columns: Arc<[String]>,
234}
235
236impl Row {
237    fn new(row: Vec<DataType>, columns: &Arc<[String]>) -> Self {
238        Self {
239            row,
240            columns: Arc::clone(columns),
241        }
242    }
243}
244
245impl Into<Vec<DataType>> for Row {
246    fn into(self) -> Vec<DataType> {
247        self.row
248    }
249}
250
251impl PartialEq<[DataType]> for Row {
252    fn eq(&self, other: &[DataType]) -> bool {
253        self.row == other
254    }
255}
256
257impl PartialEq<Vec<DataType>> for Row {
258    fn eq(&self, other: &Vec<DataType>) -> bool {
259        &self.row == other
260    }
261}
262
263impl PartialEq<&'_ Vec<DataType>> for Row {
264    fn eq(&self, other: &&Vec<DataType>) -> bool {
265        &self.row == *other
266    }
267}
268
269impl fmt::Debug for Row {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
271        f.debug_map()
272            .entries(self.columns.iter().zip(self.row.iter()))
273            .finish()
274    }
275}
276
277impl IntoIterator for Row {
278    type Item = DataType;
279    type IntoIter = std::vec::IntoIter<DataType>;
280    fn into_iter(self) -> Self::IntoIter {
281        self.row.into_iter()
282    }
283}
284
285impl AsRef<[DataType]> for Row {
286    fn as_ref(&self) -> &[DataType] {
287        &self.row[..]
288    }
289}
290
291impl Deref for Row {
292    type Target = [DataType];
293    fn deref(&self) -> &Self::Target {
294        &self.row[..]
295    }
296}
297
298impl std::ops::Index<usize> for Row {
299    type Output = DataType;
300    fn index(&self, index: usize) -> &Self::Output {
301        &self.row[index]
302    }
303}
304
305impl std::ops::Index<&'_ str> for Row {
306    type Output = DataType;
307    fn index(&self, index: &'_ str) -> &Self::Output {
308        let index = self.columns.iter().position(|col| col == index).unwrap();
309        &self.row[index]
310    }
311}
312
313impl Row {
314    /// Retrieve the field of the result by the given name as a `T`.
315    ///
316    /// Returns `None` if the given field does not exist.
317    ///
318    /// Panics if the value at the given field cannot be turned into a `T`.
319    pub fn get<T>(&self, field: &str) -> Option<T>
320    where
321        for<'a> &'a DataType: Into<T>,
322    {
323        let index = self.columns.iter().position(|col| col == field)?;
324        Some((&self.row[index]).into())
325    }
326
327    /// Remove the value for the field of the result by the given name.
328    ///
329    /// Returns `None` if the given field does not exist.
330    pub fn take(&mut self, field: &str) -> Option<DataType> {
331        let index = self.columns.iter().position(|col| col == field)?;
332        Some(std::mem::replace(&mut self.row[index], DataType::None))
333    }
334}