oracle/sql_type/
collection.rs

1use crate::sql_type::{Collection, FromSql};
2use crate::ErrorKind;
3use crate::Result;
4use std::iter::FusedIterator;
5use std::marker::PhantomData;
6
7#[derive(Clone, Debug)]
8enum State {
9    Begin,
10    Current(i32),
11    End,
12}
13
14impl State {
15    fn next(&self, coll: &Collection) -> Result<State> {
16        let index_result = match self {
17            State::Begin => coll.first_index(),
18            State::Current(index) => coll.next_index(*index),
19            State::End => return Ok(State::End),
20        };
21        match index_result {
22            Ok(index) => Ok(State::Current(index)),
23            Err(err) if err.kind() == ErrorKind::NoDataFound => Ok(State::End),
24            Err(err) => Err(err),
25        }
26    }
27
28    fn next_back(&self, coll: &Collection) -> Result<State> {
29        let index_result = match self {
30            State::Begin => return Ok(State::Begin),
31            State::Current(index) => coll.prev_index(*index),
32            State::End => coll.last_index(),
33        };
34        match index_result {
35            Ok(index) => Ok(State::Current(index)),
36            Err(err) if err.kind() == ErrorKind::NoDataFound => Ok(State::Begin),
37            Err(err) => Err(err),
38        }
39    }
40}
41
42/// An iterator over the elements of a Collection.
43///
44/// This struct is created by [`Collection::iter()`]. See its documentation for more.
45#[derive(Clone, Debug)]
46pub struct Iter<'a, T: FromSql> {
47    coll: &'a Collection,
48    state: State,
49    phantom: PhantomData<T>,
50}
51
52impl<T: FromSql> Iter<'_, T> {
53    fn try_next(&mut self) -> Result<Option<(i32, T)>> {
54        let next_state = self.state.next(self.coll)?;
55        let result = if let State::Current(index) = next_state {
56            Some((index, self.coll.get(index)?))
57        } else {
58            None
59        };
60        self.state = next_state;
61        Ok(result)
62    }
63
64    fn try_next_back(&mut self) -> Result<Option<(i32, T)>> {
65        let next_state = self.state.next_back(self.coll)?;
66        let result = if let State::Current(index) = next_state {
67            Some((index, self.coll.get(index)?))
68        } else {
69            None
70        };
71        self.state = next_state;
72        Ok(result)
73    }
74}
75
76impl<T: FromSql> Iter<'_, T> {
77    pub(crate) fn new(coll: &Collection) -> Iter<T> {
78        Iter {
79            coll,
80            state: State::Begin,
81            phantom: PhantomData,
82        }
83    }
84}
85
86impl<T> Iterator for Iter<'_, T>
87where
88    T: FromSql,
89{
90    type Item = Result<(i32, T)>;
91    fn next(&mut self) -> Option<Result<(i32, T)>> {
92        self.try_next().transpose()
93    }
94}
95
96impl<T> DoubleEndedIterator for Iter<'_, T>
97where
98    T: FromSql,
99{
100    fn next_back(&mut self) -> Option<Result<(i32, T)>> {
101        self.try_next_back().transpose()
102    }
103}
104
105impl<T: FromSql> FusedIterator for Iter<'_, T> {}
106
107/// An iterator over the values of a Collection.
108///
109/// This struct is created by [`Collection::values()`]. See its documentation for more.
110#[derive(Clone, Debug)]
111pub struct Values<'a, T: FromSql> {
112    coll: &'a Collection,
113    state: State,
114    phantom: PhantomData<T>,
115}
116
117impl<T: FromSql> Values<'_, T> {
118    fn try_next(&mut self) -> Result<Option<T>> {
119        let next_state = self.state.next(self.coll)?;
120        let result = if let State::Current(index) = next_state {
121            Some(self.coll.get(index)?)
122        } else {
123            None
124        };
125        self.state = next_state;
126        Ok(result)
127    }
128
129    fn try_next_back(&mut self) -> Result<Option<T>> {
130        let next_state = self.state.next_back(self.coll)?;
131        let result = if let State::Current(index) = next_state {
132            Some(self.coll.get(index)?)
133        } else {
134            None
135        };
136        self.state = next_state;
137        Ok(result)
138    }
139}
140
141impl<T: FromSql> Values<'_, T> {
142    pub(crate) fn new(coll: &Collection) -> Values<T> {
143        Values {
144            coll,
145            state: State::Begin,
146            phantom: PhantomData,
147        }
148    }
149}
150
151impl<T> Iterator for Values<'_, T>
152where
153    T: FromSql,
154{
155    type Item = Result<T>;
156    fn next(&mut self) -> Option<Result<T>> {
157        self.try_next().transpose()
158    }
159}
160
161impl<T> DoubleEndedIterator for Values<'_, T>
162where
163    T: FromSql,
164{
165    fn next_back(&mut self) -> Option<Result<T>> {
166        self.try_next_back().transpose()
167    }
168}
169
170impl<T: FromSql> FusedIterator for Values<'_, T> {}
171
172/// An iterator over the indices of a Collection.
173///
174/// This struct is created by [`Collection::indices()`]. See its documentation for more.
175#[derive(Clone, Debug)]
176pub struct Indices<'a> {
177    coll: &'a Collection,
178    state: State,
179}
180
181impl Indices<'_> {
182    pub(crate) fn new(coll: &Collection) -> Indices {
183        Indices {
184            coll,
185            state: State::Begin,
186        }
187    }
188
189    fn try_next(&mut self) -> Result<Option<i32>> {
190        self.state = self.state.next(self.coll)?;
191        Ok(if let State::Current(index) = self.state {
192            Some(index)
193        } else {
194            None
195        })
196    }
197
198    fn try_next_back(&mut self) -> Result<Option<i32>> {
199        self.state = self.state.next_back(self.coll)?;
200        Ok(if let State::Current(index) = self.state {
201            Some(index)
202        } else {
203            None
204        })
205    }
206}
207
208impl Iterator for Indices<'_> {
209    type Item = Result<i32>;
210    fn next(&mut self) -> Option<Result<i32>> {
211        self.try_next().transpose()
212    }
213}
214
215impl DoubleEndedIterator for Indices<'_> {
216    fn next_back(&mut self) -> Option<Result<i32>> {
217        self.try_next_back().transpose()
218    }
219}
220
221impl FusedIterator for Indices<'_> {}