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