1
//! Misc helper functions and types for use in parsing network documents
2

            
3
pub(crate) mod intern;
4
pub(crate) mod str;
5

            
6
use std::iter::Peekable;
7

            
8
/// An iterator adaptor that pauses when a given predicate is true.
9
///
10
/// Unlike std::iter::TakeWhile, it doesn't consume the first non-returned
11
/// element.
12
///
13
/// We guarantee that the predicate is called no more than once for
14
/// each item.
15
pub(crate) struct PauseAt<'a, I: Iterator, F: FnMut(&I::Item) -> bool> {
16
    /// An underlying iterator that we should take items from
17
    peek: &'a mut Peekable<I>,
18
    /// A predicate telling us which items mean that we should pause
19
    pred: F,
20
    /// Memoized value of self.pred(self.peek()), so we never
21
    /// calculate it more than once.
22
    paused: Option<bool>,
23
}
24

            
25
impl<'a, I: Iterator, F: FnMut(&I::Item) -> bool> PauseAt<'a, I, F> {
26
    /// Construct a PauseAt that will pause the iterator `peek` when the
27
    /// predicate `pred` is about to be true.
28
393
    pub(crate) fn from_peekable(peek: &'a mut Peekable<I>, pred: F) -> Self
29
393
    where
30
393
        F: FnMut(&I::Item) -> bool,
31
393
    {
32
393
        PauseAt {
33
393
            peek,
34
393
            pred,
35
393
            paused: None,
36
393
        }
37
393
    }
38
    /// Replace the predicate on a PauseAt, returning a new PauseAt.
39
    #[cfg(any(test, feature = "routerdesc"))]
40
19
    pub(crate) fn new_pred<F2>(self, pred: F2) -> PauseAt<'a, I, F2>
41
19
    where
42
19
        F2: FnMut(&I::Item) -> bool,
43
19
    {
44
19
        PauseAt::from_peekable(self.peek, pred)
45
19
    }
46
    /// Unwrap this PauseAt, returning its underlying Peekable.
47
    #[allow(unused)]
48
1
    pub(crate) fn remaining(self) -> &'a mut Peekable<I> {
49
1
        self.peek
50
1
    }
51
    /// Return the next item that will be yielded from this iterator, or
52
    /// None if this iterator is about to yield None.
53
    #[allow(unused)]
54
5
    pub(crate) fn peek(&mut self) -> Option<&I::Item> {
55
5
        // TODO: I wish it weren't necessary for this function to take
56
5
        // a mutable reference.
57
5
        if self.check_paused() {
58
2
            None
59
        } else {
60
3
            self.peek.peek()
61
        }
62
5
    }
63
    /// Helper: Return true if we will pause before the next element,
64
    /// and false otherwise.  Store the value in self.paused, so that
65
    /// we don't invoke self.pred more than once.
66
    fn check_paused(&mut self) -> bool {
67
2520
        if let Some(p) = self.paused {
68
5
            return p;
69
2515
        }
70
2515
        if let Some(nextval) = self.peek.peek() {
71
2390
            let p = (self.pred)(nextval);
72
2390
            self.paused = Some(p);
73
2390
            p
74
        } else {
75
124
            self.paused = Some(false);
76
124
            false
77
        }
78
2519
    }
79
}
80

            
81
impl<'a, I: Iterator, F: FnMut(&I::Item) -> bool> Iterator for PauseAt<'a, I, F> {
82
    type Item = I::Item;
83
2515
    fn next(&mut self) -> Option<Self::Item> {
84
2515
        if self.check_paused() {
85
267
            None
86
        } else {
87
2248
            self.paused = None;
88
2248
            self.peek.next()
89
        }
90
2515
    }
91
}
92

            
93
/// A Private module for declaring a "sealed" trait.
94
pub(crate) mod private {
95
    /// A non-exported trait, used to prevent others from implementing a trait.
96
    ///
97
    /// For more information on this pattern, see [the Rust API
98
    /// guidelines](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-sealed).
99
    pub trait Sealed {}
100
}
101

            
102
#[cfg(test)]
103
mod tests {
104

            
105
    #[test]
106
    fn test_pause_at() {
107
        use super::PauseAt;
108
        let mut iter = (1..10).into_iter().peekable();
109
        let mut iter = PauseAt::from_peekable(&mut iter, |x| *x == 3);
110

            
111
        assert_eq!(iter.next(), Some(1));
112
        assert_eq!(iter.next(), Some(2));
113
        assert_eq!(iter.next(), None);
114

            
115
        let mut iter = iter.new_pred(|x| *x > 5);
116
        assert_eq!(iter.next(), Some(3));
117
        assert_eq!(iter.next(), Some(4));
118
        assert_eq!(iter.next(), Some(5));
119
        assert_eq!(iter.peek(), None);
120
        assert_eq!(iter.next(), None);
121

            
122
        let iter = iter.remaining();
123
        assert_eq!(iter.next(), Some(6));
124
        assert_eq!(iter.peek(), Some(&7));
125
        assert_eq!(iter.next(), Some(7));
126
        assert_eq!(iter.next(), Some(8));
127
        assert_eq!(iter.next(), Some(9));
128
        assert_eq!(iter.peek(), None);
129
        assert_eq!(iter.next(), None);
130
    }
131

            
132
    #[test]
133
    fn test_parse_at_mutable() {
134
        use super::PauseAt;
135
        let mut count = 0;
136
        let mut iter = (1..10).into_iter().peekable();
137
        // pause at the third item, using mutable state in the closure.
138
        let mut iter = PauseAt::from_peekable(&mut iter, |_| {
139
            count += 1;
140
            count == 4
141
        });
142
        assert_eq!(iter.peek(), Some(&1)); // we can do this multiple times,
143
        assert_eq!(iter.peek(), Some(&1)); // but count isn't advanced.
144
        assert_eq!(iter.next(), Some(1));
145

            
146
        assert_eq!(iter.next(), Some(2));
147
        assert_eq!(iter.peek(), Some(&3));
148
        assert_eq!(iter.next(), Some(3));
149
        assert_eq!(iter.peek(), None);
150
        assert_eq!(iter.next(), None);
151
    }
152
}