]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/sources/once_with.rs
make unaligned_reference a hard error
[rust.git] / library / core / src / iter / sources / once_with.rs
1 use crate::fmt;
2 use 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 generator 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")]
61 pub 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")]
72 pub struct OnceWith<F> {
73     gen: Option<F>,
74 }
75
76 #[stable(feature = "iter_once_with_debug", since = "CURRENT_RUSTC_VERSION")]
77 impl<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("OnceWith(Some(_))")
81         } else {
82             f.write_str("OnceWith(None)")
83         }
84     }
85 }
86
87 #[stable(feature = "iter_once_with", since = "1.43.0")]
88 impl<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 = 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")]
104 impl<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")]
111 impl<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")]
118 impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
119
120 #[stable(feature = "iter_once_with", since = "1.43.0")]
121 unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}