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`](crate::slices::SliceByValueSubsliceGat) for
16/// more information.
17pub trait IterateByValueGat<'a, __Implicit: ImplBound = Ref<'a, Self>> {
18    /// The type of the items returned by the iterator.
19    type Item;
20    /// The type of the iterator returned by
21    /// [`iter_value`](IterateByValue::iter_value).
22    type Iter: 'a + Iterator<Item = Self::Item>;
23}
24
25/// A convenience type representing the type of iterator returned by a type
26/// implementing [`IterateByValueGat`].
27pub type Iter<'a, T> = <T as IterateByValueGat<'a>>::Iter;
28
29impl<'a, T: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for &T {
30    type Item = T::Item;
31    type Iter = T::Iter;
32}
33
34impl<'a, T: IterateByValueGat<'a> + ?Sized> IterateByValueGat<'a> for &mut T {
35    type Item = T::Item;
36    type Iter = T::Iter;
37}
38
39/// A trait for obtaining a by-value iterator.
40///
41/// This trait necessary as all standard Rust containers already have
42/// [`IntoIterator`]-based methods for obtaining reference-based iterators.
43///
44/// Note that [`iter_value`](IterateByValue::iter_value) returns a standard
45/// iterator. However, the intended semantics is that the iterator will return
46/// values.
47///
48/// If you need to iterate from a given position, and you can implement such an
49/// iterator more efficiently, please consider [`IterateByValueFrom`].
50///
51/// ## Binding the Iterator Type
52///
53/// To bind the iterator type or the type of its items you need to use
54/// higher-rank trait bounds, as in:
55///
56/// ```rust
57/// use value_traits::iter::*;
58///
59/// fn f<S>(s: S) where
60///    S: IterateByValue + for<'a> IterateByValueGat<'a, Iter = std::slice::Iter<'a, usize>>,
61/// {
62///     let _: std::slice::Iter<'_, usize> = s.iter_value();
63/// }
64/// ```
65///
66/// You can also bind the iterator using traits:
67///
68/// ```rust
69/// use value_traits::iter::*;
70///
71/// fn f<S>(s: S) where
72///    S: IterateByValue + for<'a> IterateByValueGat<'a, Iter: ExactSizeIterator>,
73/// {
74///     let _ = s.iter_value().len();
75/// }
76/// ```
77///
78/// In this case, you can equivalently use the [`Iter`] type alias, which might
79/// be more concise:
80///
81/// ```rust
82/// use value_traits::iter::*;
83///
84/// fn f<S>(s: S) where
85///    S: IterateByValue,
86///    for<'a> Iter<'a, S>: ExactSizeIterator,
87/// {
88///     let _ = s.iter_value().len();
89/// }
90/// ```
91///
92/// As it happens for
93/// [`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html),
94/// it is possible to bind the type of the items returned by the iterator
95/// without referring to the iterator type 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/// ```
120pub trait IterateByValue: for<'a> IterateByValueGat<'a> {
121    /// Returns an iterator on values.
122    fn iter_value(&self) -> Iter<'_, Self>;
123}
124
125impl<T: IterateByValue + ?Sized> IterateByValue for &T {
126    fn iter_value(&self) -> Iter<'_, Self> {
127        (**self).iter_value()
128    }
129}
130
131impl<T: IterateByValue + ?Sized> IterateByValue for &mut T {
132    fn iter_value(&self) -> Iter<'_, Self> {
133        (**self).iter_value()
134    }
135}
136
137/// A GAT-like trait specifying the type of a by-value iterator starting from
138/// a given position.
139///
140/// See [`SliceByValueSubsliceGat`](crate::slices::SliceByValueSubsliceGat) for
141/// more information.
142pub trait IterateByValueFromGat<'a, __Implicit: ImplBound = Ref<'a, Self>> {
143    /// The type of the items returned by the iterator.
144    type Item;
145    /// The type of the iterator returned by
146    /// [`iter_value_from`](IterateByValueFrom::iter_value_from).
147    type IterFrom: 'a + Iterator<Item = Self::Item>;
148}
149
150impl<'a, T: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for &T {
151    type Item = T::Item;
152    type IterFrom = T::IterFrom;
153}
154
155impl<'a, T: IterateByValueFromGat<'a> + ?Sized> IterateByValueFromGat<'a> for &mut T {
156    type Item = T::Item;
157    type IterFrom = T::IterFrom;
158}
159
160/// A convenience type representing the type of iterator returned by a type
161/// implementing [`IterateByValueFromGat`].
162pub type IterFrom<'a, T> = <T as IterateByValueFromGat<'a>>::IterFrom;
163
164/// A trait for obtaining a by-value iterator starting from a given position.
165///
166/// This is a version of [`IterateByValue`] that is useful for types in which
167/// obtaining a global iterator and skipping is expensive.
168///
169/// We cannot provide a skip-based default implementation because the returned
170/// type is not necessarily the same type as that returned by
171/// [`IterateByValue::iter_value`], but you are free to implement
172/// [`iter_value_from`](IterateByValueFrom::iter_value_from) that way.
173///
174/// ## Binding the Iterator Type
175///
176/// To bind the iterator type or the type of its items you need to use
177/// higher-rank trait bounds, as in:
178///
179/// ```rust
180/// use value_traits::iter::*;
181///
182/// fn f<S>(s: S) where
183///    S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, IterFrom = std::slice::Iter<'a, usize>>,
184/// {
185///     let _: std::slice::Iter<'_, usize> = s.iter_value_from(0);
186/// }
187/// ```
188///
189/// You can also bind the iterator using traits:
190///
191/// ```rust
192/// use value_traits::iter::*;
193///
194/// fn f<S>(s: S) where
195///    S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, IterFrom: ExactSizeIterator>,
196/// {
197///     let _ = s.iter_value_from(0).len();
198/// }
199/// ```
200///
201/// In this case, you can equivalently use the [`IterFrom`] type alias, which
202/// might be more concise:
203///
204/// ```rust
205/// use value_traits::iter::*;
206///
207/// fn f<S>(s: S) where
208///    S: IterateByValueFrom,
209///    for<'a> IterFrom<'a, S>: ExactSizeIterator,
210/// {
211///     let _ = s.iter_value_from(0).len();
212/// }
213/// ```
214///
215/// As it happens for
216/// [`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html),
217/// it is possible to bind the type of the items returned by the iterator
218/// without referring to the iterator type itself:
219///
220/// ```rust
221/// use value_traits::iter::*;
222///
223/// fn f<S>(s: S) where
224///    S: IterateByValueFrom + for<'a> IterateByValueFromGat<'a, Item = usize>,
225/// {
226///     let _: Option<usize> = s.iter_value_from(0).next();
227/// }
228/// ```
229///
230/// Once again, the [`IterFrom`] type alias can be used to make the bound more
231/// concise:
232///
233/// ```rust
234/// use value_traits::iter::*;
235///
236/// fn f<S>(s: S) where
237///    S: IterateByValueFrom,
238///    for<'a> IterFrom<'a, S>: Iterator<Item = usize>,
239/// {
240///     let _: Option<usize> = s.iter_value_from(0).next();
241/// }
242/// ```
243pub trait IterateByValueFrom: for<'a> IterateByValueFromGat<'a> {
244    /// Returns an iterator on values starting at the given position.
245    fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self>;
246}
247
248impl<T: IterateByValueFrom + ?Sized> IterateByValueFrom for &T {
249    fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
250        (**self).iter_value_from(from)
251    }
252}
253
254impl<T: IterateByValueFrom + ?Sized> IterateByValueFrom for &mut T {
255    fn iter_value_from(&self, from: usize) -> IterFrom<'_, Self> {
256        (**self).iter_value_from(from)
257    }
258}