rta_for_fps_lib/iterators/
peek.rs

1//! Module for the `Peeker` and `PeekRef` implementation and definition
2
3use core::marker::PhantomData;
4use core::ops::{Deref, DerefMut};
5use core::ptr::NonNull;
6
7/// Smart Pointer to a Peek Element
8/// allows viewing, modifying and taking the Peek Element
9#[derive(Debug)]
10pub struct PeekRef<'a, I> {
11    /// The reference to the nested options containing the Peek Element
12    #[allow(clippy::option_option)]
13    container: NonNull<Option<Option<I>>>,
14    /// The reference to the element contained in the above options
15    inner: NonNull<I>,
16    /// make sure we have the correct variance and
17    /// the only one with access to the original reference
18    /// while we are alive
19    mut_ref: PhantomData<&'a mut I>,
20}
21
22impl<'a, I> Deref for PeekRef<'a, I> {
23    type Target = I;
24
25    fn deref(&self) -> &Self::Target {
26        self.as_ref()
27    }
28}
29
30impl<'a, I> DerefMut for PeekRef<'a, I> {
31    fn deref_mut(&mut self) -> &mut Self::Target {
32        self.as_mut()
33    }
34}
35
36impl<'a, I> PeekRef<'a, I> {
37    /// Create a new `PeekRef` for the nested Options
38    #[allow(clippy::option_option)]
39    pub fn new(option: &'a mut Option<Option<I>>) -> Option<PeekRef<'a, I>> {
40        let option_ref = NonNull::from(&*option);
41        option
42            .as_mut()
43            .and_then(core::option::Option::as_mut)
44            .map(|inner| PeekRef {
45                container: option_ref,
46                inner: NonNull::from(inner),
47                mut_ref: PhantomData::<&'a mut I>,
48            })
49    }
50
51    /// Consume the `PeekRef` and get the peek element
52    #[allow(clippy::must_use_candidate)]
53    pub fn take(mut self) -> I {
54        unsafe {
55            // Safety:
56            // This type is constructed from mutable references to Options that contain the Some variant
57            // This types interface makes sure that the inner pointer stays valid until this value is
58            // dropped or take is called
59            //
60            // As we consume self it is safe to invalidate inner as we don't use it here
61            // and drop our self at the end of the function
62            self.container.as_mut()
63        }
64        .take()
65        .flatten()
66        .expect("Constructed only for Some variant containing Some variant")
67    }
68
69    /// Get a mutable reference to the peek element
70    fn as_mut(&mut self) -> &mut I {
71        unsafe {
72            // Safety:
73            // This type is constructed from mutable references to Options that contain the Some variant
74            // This types interface makes sure that the inner pointer stays valid until this value is
75            // dropped or take is called
76            //
77            // As we have a mutable reference to self we can't have given out another reference
78            // currently
79            self.inner.as_mut()
80        }
81    }
82    /// Get an immutable reference to the peek element
83    fn as_ref(&self) -> &I {
84        unsafe {
85            // Safety:
86            // This type is constructed from mutable references to Options that contain the Some variant
87            // This types interface makes sure that the inner pointer stays valid until this value is
88            // dropped or take is called
89            //
90            // As we have a reference to self we can't have given out a mutable reference
91            // currently
92            self.inner.as_ref()
93        }
94    }
95}
96
97/// A version of the standard libraries [`Peekable`](core::iter::Peekable) that lets one restore/replace/clear the peek element
98#[derive(Debug, Clone)]
99pub struct Peeker<I, IT> {
100    /// The iterator we are peeking into
101    iter: I,
102    /// If Some contains the peeked at value
103    /// which may be a None
104    /// Otherwise we have not peeked since the last next call
105    /// or the value was taken via a PeekRef
106    #[allow(clippy::option_option)]
107    peek_window: Option<Option<IT>>,
108}
109
110impl<I, IT> Peeker<I, IT>
111where
112    I: Iterator<Item = IT>,
113{
114    /// Create a new `Peeker`
115    pub fn new(inner: I) -> Self {
116        Self {
117            iter: inner,
118            peek_window: None,
119        }
120    }
121
122    /// Take a peek at the element that will be returned from the next next call
123    pub fn peek(&mut self) -> Option<&IT> {
124        self.peek_ref_mut().as_ref()
125    }
126
127    /// Take a mutable peek at the element that will be returned from the next next call
128    /// Changing the value behind the reference will change the next element
129    pub fn peek_mut(&mut self) -> Option<&mut IT> {
130        self.peek_ref_mut().as_mut()
131    }
132
133    /// Peek into the iterator if not done already and get a `PeekRef`
134    /// to the peeked value if it was Some
135    pub fn peek_ref(&mut self) -> Option<PeekRef<'_, IT>> {
136        self.peek_ref_mut();
137        PeekRef::new(&mut self.peek_window)
138    }
139
140    /// Make sure the peek slot is filled and return a mutable reference to the inner option
141    fn peek_ref_mut(&mut self) -> &mut Option<IT> {
142        let iter = &mut self.iter;
143        self.peek_window.get_or_insert_with(|| iter.next())
144    }
145
146    /// Set a peek window if there currently is none
147    ///
148    /// # Panics
149    /// If there is a window held as peek
150    pub fn restore_peek(&mut self, window: IT) {
151        if self.peek_window.take().flatten().is_none() {
152            self.peek_window = Some(Some(window))
153        } else {
154            panic!("Restoring over existing peek window!")
155        }
156    }
157}
158
159impl<I, IT> Iterator for Peeker<I, IT>
160where
161    I: Iterator<Item = IT>,
162{
163    type Item = IT;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        self.peek_window.take().unwrap_or_else(|| self.iter.next())
167    }
168}