Skip to main content

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}