]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/sources/once_with.rs
Rollup merge of #79293 - Havvy:test-eval-order-compound-assign, r=Mark-Simulacrum
[rust.git] / library / core / src / iter / sources / once_with.rs
1 use crate::iter::{FusedIterator, TrustedLen};
2
3 /// Creates an iterator that lazily generates a value exactly once by invoking
4 /// the provided closure.
5 ///
6 /// This is commonly used to adapt a single value generator into a [`chain()`] of
7 /// other kinds of iteration. Maybe you have an iterator that covers almost
8 /// everything, but you need an extra special case. Maybe you have a function
9 /// which works on iterators, but you only need to process one value.
10 ///
11 /// Unlike [`once()`], this function will lazily generate the value on request.
12 ///
13 /// [`chain()`]: Iterator::chain
14 /// [`once()`]: crate::iter::once
15 ///
16 /// # Examples
17 ///
18 /// Basic usage:
19 ///
20 /// ```
21 /// use std::iter;
22 ///
23 /// // one is the loneliest number
24 /// let mut one = iter::once_with(|| 1);
25 ///
26 /// assert_eq!(Some(1), one.next());
27 ///
28 /// // just one, that's all we get
29 /// assert_eq!(None, one.next());
30 /// ```
31 ///
32 /// Chaining together with another iterator. Let's say that we want to iterate
33 /// over each file of the `.foo` directory, but also a configuration file,
34 /// `.foorc`:
35 ///
36 /// ```no_run
37 /// use std::iter;
38 /// use std::fs;
39 /// use std::path::PathBuf;
40 ///
41 /// let dirs = fs::read_dir(".foo").unwrap();
42 ///
43 /// // we need to convert from an iterator of DirEntry-s to an iterator of
44 /// // PathBufs, so we use map
45 /// let dirs = dirs.map(|file| file.unwrap().path());
46 ///
47 /// // now, our iterator just for our config file
48 /// let config = iter::once_with(|| PathBuf::from(".foorc"));
49 ///
50 /// // chain the two iterators together into one big iterator
51 /// let files = dirs.chain(config);
52 ///
53 /// // this will give us all of the files in .foo as well as .foorc
54 /// for f in files {
55 ///     println!("{:?}", f);
56 /// }
57 /// ```
58 #[inline]
59 #[stable(feature = "iter_once_with", since = "1.43.0")]
60 pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
61     OnceWith { gen: Some(gen) }
62 }
63
64 /// An iterator that yields a single element of type `A` by
65 /// applying the provided closure `F: FnOnce() -> A`.
66 ///
67 /// This `struct` is created by the [`once_with()`] function.
68 /// See its documentation for more.
69 #[derive(Clone, Debug)]
70 #[stable(feature = "iter_once_with", since = "1.43.0")]
71 pub struct OnceWith<F> {
72     gen: Option<F>,
73 }
74
75 #[stable(feature = "iter_once_with", since = "1.43.0")]
76 impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
77     type Item = A;
78
79     #[inline]
80     fn next(&mut self) -> Option<A> {
81         let f = self.gen.take()?;
82         Some(f())
83     }
84
85     #[inline]
86     fn size_hint(&self) -> (usize, Option<usize>) {
87         self.gen.iter().size_hint()
88     }
89 }
90
91 #[stable(feature = "iter_once_with", since = "1.43.0")]
92 impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
93     fn next_back(&mut self) -> Option<A> {
94         self.next()
95     }
96 }
97
98 #[stable(feature = "iter_once_with", since = "1.43.0")]
99 impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
100     fn len(&self) -> usize {
101         self.gen.iter().len()
102     }
103 }
104
105 #[stable(feature = "iter_once_with", since = "1.43.0")]
106 impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
107
108 #[stable(feature = "iter_once_with", since = "1.43.0")]
109 unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}