value_traits/traits/iter.rs
1/*
2 * SPDX-FileCopyrightText: 2025 Tommaso Fontana
3 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
4 * SPDX-FileCopyrightText: 2025 Inria
5 *
6 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7 */
8
9//! Traits for by-value iterators.
10
11use crate::{ImplBound, Ref};
12
13/// A GAT-like trait specifying the type of a by-value iterator.
14///
15/// See [`SliceByValueSubsliceGat`] for more information.
16///
17/// [`SliceByValueSubsliceGat`]: crate::slices::SliceByValueSubsliceGat
18pub trait IterateByValueGat<'a, __Implicit: ImplBound = Ref<'a, Self>> {
19 /// The type of the items returned by the iterator.
20 type Item;
21 /// The type of the iterator returned by [`iter_value`].
22 ///
23 /// [`iter_value`]: IterateByValue::iter_value
24 type Iter: 'a + Iterator<Item = Self::Item>;
25}
26
27/// A convenience type representing the type of iterator returned by a type
28/// implementing [`IterateByValueGat`].
29pub type Iter<'a, T> = <T as IterateByValueGat<'a>>::Iter;
30
31impl<'a, T: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for &T {
32 type Item = T::Item;
33 type Iter = T::Iter;
34}
35
36impl<'a, T: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for &mut T {
37 type Item = T::Item;
38 type Iter = T::Iter;
39}
40
41/// A trait for obtaining a by-value iterator.
42///
43/// This trait is necessary as all standard Rust containers already have
44/// [`IntoIterator`]-based methods for obtaining reference-based iterators.
45///
46/// Note that [`iter_value`] returns a standard iterator. However, the
47/// intended semantics is that the iterator will return values.
48///
49/// If you need to iterate from a given position, and you can implement such an
50/// iterator more efficiently, please consider [`IterateByValueFrom`].
51///
52/// ## Binding the Iterator Type
53///
54/// To bind the iterator type or the type of its items you need to use
55/// higher-rank trait bounds, as in:
56///
57/// ```rust
58/// use value_traits::iter::*;
59///
60/// fn f<S>(s: S) where
61/// S: IterateByValue + for<'a> IterateByValueGat<'a, Iter = std::slice::Iter<'a, usize>>,
62/// {
63/// let _: std::slice::Iter<'_, usize> = s.iter_value();
64/// }
65/// ```
66///
67/// You can also bind the iterator using traits:
68///
69/// ```rust
70/// use value_traits::iter::*;
71///
72/// fn f<S>(s: S) where
73/// S: IterateByValue + for<'a> IterateByValueGat<'a, Iter: ExactSizeIterator>,
74/// {
75/// let _ = s.iter_value().len();
76/// }
77/// ```
78///
79/// In this case, you can equivalently use the [`Iter`] type alias, which might
80/// be more concise:
81///
82/// ```rust
83/// use value_traits::iter::*;
84///
85/// fn f<S>(s: S) where
86/// S: IterateByValue,
87/// for<'a> Iter<'a, S>: ExactSizeIterator,
88/// {
89/// let _ = s.iter_value().len();
90/// }
91/// ```
92///
93/// As it happens for [`IntoIterator`], it is possible to bind the type of the
94/// items returned by the iterator without referring to the iterator type
95/// itself:
96///
97/// ```rust
98/// use value_traits::iter::*;
99///
100/// fn f<S>(s: S) where
101/// S: IterateByValue + for<'a> IterateByValueGat<'a, Item = usize>,
102/// {
103/// let _: Option<usize> = s.iter_value().next();
104/// }
105/// ```
106///
107/// Once again, the [`Iter`] type alias can be used to make the bound more
108/// concise:
109///
110/// ```rust
111/// use value_traits::iter::*;
112///
113/// fn f<S>(s: S) where
114/// S: IterateByValue,
115/// for<'a> Iter<'a, S>: Iterator<Item = usize>,
116/// {
117/// let _: Option<usize> = s.iter_value().next();
118/// }
119/// ```
120///
121/// [`iter_value`]: IterateByValue::iter_value
122pub trait IterateByValue: for<'a> IterateByValueGat<'a> {
123 /// Returns an iterator on values.
124 fn iter_value(&self) -> Iter<'_, Self>;
125}
126
127impl<T: IterateByValue + ?Sized> IterateByValue for &T {
128 fn iter_value(&self) -> Iter<'_, Self> {
129 (**self).iter_value()
130 }
131}
132
133impl<T: IterateByValue + ?Sized> IterateByValue for &mut T {
134 fn iter_value(&self) -> Iter<'_, Self> {
135 (**self).iter_value()
136 }
137}
138
139/// A GAT-like trait specifying the type of a by-value iterator starting from
140/// a given position.
141///
142/// See [`SliceByValueSubsliceGat`] for more information.
143///
144/// [`SliceByValueSubsliceGat`]: crate::slices::SliceByValueSubsliceGat
145pub trait IterateByValueFromGat<'a, __Implicit: ImplBound = Ref<'a, Self>> {
146 /// The type of the items returned by the iterator.
147 type Item;
148 /// The type of the iterator returned by [`iter_value_from`].
149 ///
150 /// [`iter_value_from`]: IterateByValueFrom::iter_value_from
151 type IterFrom: 'a + Iterator<Item = Self::Item>;
152}
153
154impl<'a, T: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for &T {
155 type Item = T::Item;
156 type IterFrom = T::IterFrom;
157}
158
159impl<'a, T: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for &mut T {
160 type Item = T::Item;
161 type IterFrom = T::IterFrom;
162}
163
164/// A convenience type representing the type of iterator returned by a type
165/// implementing [`IterateByValueFromGat`].
166pub type IterFrom<'a, T> = <T as IterateByValueFromGat<'a>>::IterFrom;
167
168/// A trait for obtaining a by-value iterator starting from a given position.
169///
170/// This is a version of [`IterateByValue`] that is useful for types in which
171/// obtaining a global iterator and skipping is expensive.
172///
173/// We cannot provide a skip-based default implementation because the returned
174/// type is not necessarily the same type as that returned by
175/// [`IterateByValue::iter_value`], but you are free to implement
176/// [`iter_value_from`] that way.
177///
178/// ## Binding the Iterator Type
179///
180/// To bind the iterator type or the type of its items you need to use
181/// higher-rank trait bounds, as in:
182///
183/// ```rust
184/// use value_traits::iter::*;
185///
186/// fn f<S>(s: S) where
187/// S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, IterFrom = std::slice::Iter<'a, usize>>,
188/// {
189/// let _: std::slice::Iter<'_, usize> = s.iter_value_from(0);
190/// }
191/// ```
192///
193/// You can also bind the iterator using traits:
194///
195/// ```rust
196/// use value_traits::iter::*;
197///
198/// fn f<S>(s: S) where
199/// S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, IterFrom: ExactSizeIterator>,
200/// {
201/// let _ = s.iter_value_from(0).len();
202/// }
203/// ```
204///
205/// In this case, you can equivalently use the [`IterFrom`] type alias, which
206/// might be more concise:
207///
208/// ```rust
209/// use value_traits::iter::*;
210///
211/// fn f<S>(s: S) where
212/// S: IterateByValueFrom,
213/// for<'a> IterFrom<'a, S>: ExactSizeIterator,
214/// {
215/// let _ = s.iter_value_from(0).len();
216/// }
217/// ```
218///
219/// As it happens for [`IntoIterator`], it is possible to bind the type of the
220/// items returned by the iterator without referring to the iterator type
221/// itself:
222///
223/// ```rust
224/// use value_traits::iter::*;
225///
226/// fn f<S>(s: S) where
227/// S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, Item = usize>,
228/// {
229/// let _: Option<usize> = s.iter_value_from(0).next();
230/// }
231/// ```
232///
233/// Once again, the [`IterFrom`] type alias can be used to make the bound more
234/// concise:
235///
236/// ```rust
237/// use value_traits::iter::*;
238///
239/// fn f<S>(s: S) where
240/// S: IterateByValueFrom,
241/// for<'a> IterFrom<'a, S>: Iterator<Item = usize>,
242/// {
243/// let _: Option<usize> = s.iter_value_from(0).next();
244/// }
245/// ```
246///
247/// [`iter_value_from`]: IterateByValueFrom::iter_value_from
248pub trait IterateByValueFrom: for<'a> IterateByValueFromGat<'a> {
249 /// Returns an iterator on values starting at the given position.
250 ///
251 /// Iterating from the length of the structure is allowed, and returns an
252 /// exhausted iterator.
253 ///
254 /// # Panics
255 ///
256 /// This method will panic if `from` is greater than the length of the
257 /// structure being iterated, mirroring the behavior of slice indexing.
258 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self>;
259}
260
261impl<T: IterateByValueFrom + ?Sized> IterateByValueFrom for &T {
262 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
263 (**self).iter_value_from(from)
264 }
265}
266
267impl<T: IterateByValueFrom + ?Sized> IterateByValueFrom for &mut T {
268 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
269 (**self).iter_value_from(from)
270 }
271}
272
273#[cfg(feature = "alloc")]
274mod alloc_impls {
275 use super::*;
276 #[cfg(all(feature = "alloc", not(feature = "std")))]
277 use alloc::boxed::Box;
278
279 impl<'a, S: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for Box<S> {
280 type Item = S::Item;
281 type Iter = S::Iter;
282 }
283
284 impl<S: IterateByValue + ?Sized> IterateByValue for Box<S> {
285 fn iter_value(&self) -> Iter<'_, Self> {
286 (**self).iter_value()
287 }
288 }
289
290 impl<'a, S: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for Box<S> {
291 type Item = S::Item;
292 type IterFrom = S::IterFrom;
293 }
294
295 impl<S: IterateByValueFrom + ?Sized> IterateByValueFrom for Box<S> {
296 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
297 (**self).iter_value_from(from)
298 }
299 }
300}
301
302#[cfg(feature = "std")]
303mod std_impls {
304 use super::*;
305 use std::{rc::Rc, sync::Arc};
306
307 impl<'a, S: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for Arc<S> {
308 type Item = S::Item;
309 type Iter = S::Iter;
310 }
311
312 impl<S: IterateByValue + ?Sized> IterateByValue for Arc<S> {
313 fn iter_value(&self) -> Iter<'_, Self> {
314 (**self).iter_value()
315 }
316 }
317
318 impl<'a, S: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for Arc<S> {
319 type Item = S::Item;
320 type IterFrom = S::IterFrom;
321 }
322
323 impl<S: IterateByValueFrom + ?Sized> IterateByValueFrom for Arc<S> {
324 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
325 (**self).iter_value_from(from)
326 }
327 }
328
329 impl<'a, S: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for Rc<S> {
330 type Item = S::Item;
331 type Iter = S::Iter;
332 }
333
334 impl<S: IterateByValue + ?Sized> IterateByValue for Rc<S> {
335 fn iter_value(&self) -> Iter<'_, Self> {
336 (**self).iter_value()
337 }
338 }
339
340 impl<'a, S: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for Rc<S> {
341 type Item = S::Item;
342 type IterFrom = S::IterFrom;
343 }
344
345 impl<S: IterateByValueFrom + ?Sized> IterateByValueFrom for Rc<S> {
346 fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
347 (**self).iter_value_from(from)
348 }
349 }
350}