tokio_postgres_extractor/iter.rs
1//! Extension traits for working with iterators over [`Row`]s.
2//!
3//! Using these extension traits, iterators over [`Row`]s can be turned into iterators
4//! over [`Extract`]able types.
5//!
6//! # Examples
7//!
8//! ```
9//! # use tokio_postgres::Row;
10//! # use tokio_postgres_extractor::{Columns, Extract};
11//! # use tokio_postgres_extractor::iter::IterExtractRefExt;
12//! #[derive(Columns, Extract)]
13//! struct User<'a> {
14//! id: i32,
15//! name: &'a str,
16//! }
17//!
18//! fn extract_users<'a>(i: impl Iterator<Item = &'a Row>) -> Vec<User<'a>> {
19//! i.extract_ref().collect()
20//! }
21//! ```
22
23use {
24 crate::{
25 iter::sealed::{Sealed1, Sealed2},
26 Extract, ExtractOwned,
27 },
28 tokio_postgres::Row,
29};
30
31#[cfg(test)]
32mod tests;
33
34/// An iterator over `T`s that are extracted from [`Row`]s.
35///
36/// Construct it using [`IterExtractExt::extract`].
37///
38/// # Panics
39///
40/// The iterator panics if [`Extract::extract`] panics.
41pub struct ExtractIter<T, I>
42where
43 T: ExtractOwned,
44 I: Iterator<Item = Row>,
45{
46 iter: I,
47 columns: Option<T::Columns>,
48}
49
50impl<T, I> Iterator for ExtractIter<T, I>
51where
52 T: ExtractOwned,
53 I: Iterator<Item = Row>,
54{
55 type Item = T;
56
57 fn next(&mut self) -> Option<Self::Item> {
58 Some(T::extract(&mut self.columns, &self.iter.next()?))
59 }
60}
61
62/// Extension trait for extracting from an iterator over [`Row`].
63pub trait IterExtractExt: Iterator<Item = Row> + Sized + Sealed2 {
64 /// Turns the iterator into an iterator over `T`.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// # use tokio_postgres::Row;
70 /// # use tokio_postgres_extractor::iter::IterExtractExt;
71 /// # use tokio_postgres_extractor::{Columns, Extract};
72 /// #[derive(Columns, Extract)]
73 /// struct User {
74 /// id: i32,
75 /// name: String,
76 /// }
77 ///
78 /// fn extract_users(i: impl Iterator<Item = Row>) -> Vec<User> {
79 /// i.extract().collect()
80 /// }
81 fn extract<T: ExtractOwned>(self) -> ExtractIter<T, Self>;
82}
83
84impl<I> Sealed2 for I where I: Iterator<Item = Row> {}
85
86impl<I> IterExtractExt for I
87where
88 I: Iterator<Item = Row>,
89{
90 fn extract<T: ExtractOwned>(self) -> ExtractIter<T, Self> {
91 ExtractIter {
92 iter: self,
93 columns: None,
94 }
95 }
96}
97
98/// An iterator over `T`s that are extracted from [`&Row`][Row]s.
99///
100/// Construct it using [`IterExtractRefExt::extract_ref`].
101///
102/// # Panics
103///
104/// The iterator panics if [`Extract::extract`] panics.
105pub struct ExtractIterRef<'a, T, I>
106where
107 T: Extract<'a>,
108 I: Iterator<Item = &'a Row>,
109{
110 iter: I,
111 columns: Option<T::Columns>,
112}
113
114impl<'a, T, I> Iterator for ExtractIterRef<'a, T, I>
115where
116 T: Extract<'a>,
117 I: Iterator<Item = &'a Row>,
118{
119 type Item = T;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 Some(T::extract(&mut self.columns, self.iter.next()?))
123 }
124}
125
126/// Extension trait for extracting from an iterator over [`&Row`][Row].
127pub trait IterExtractRefExt<'a>: Iterator<Item = &'a Row> + Sized + Sealed1 {
128 /// Turns the iterator into an iterator over `T`.
129 ///
130 /// # Examples
131 ///
132 /// ```
133 /// # use tokio_postgres::Row;
134 /// # use tokio_postgres_extractor::iter::IterExtractRefExt;
135 /// # use tokio_postgres_extractor::{Columns, Extract};
136 /// #[derive(Columns, Extract)]
137 /// struct User<'a> {
138 /// id: i32,
139 /// name: &'a str,
140 /// }
141 ///
142 /// fn extract_users<'a>(i: impl Iterator<Item = &'a Row>) -> Vec<User<'a>> {
143 /// i.extract_ref().collect()
144 /// }
145 /// ```
146 fn extract_ref<T: Extract<'a>>(self) -> ExtractIterRef<'a, T, Self>;
147}
148
149impl<'a, I> Sealed1 for I where I: Iterator<Item = &'a Row> {}
150
151impl<'a, I> IterExtractRefExt<'a> for I
152where
153 I: Iterator<Item = &'a Row>,
154{
155 fn extract_ref<T: Extract<'a>>(self) -> ExtractIterRef<'a, T, Self> {
156 ExtractIterRef {
157 iter: self,
158 columns: None,
159 }
160 }
161}
162
163mod sealed {
164 pub trait Sealed1 {}
165 pub trait Sealed2 {}
166}