seq_watcher/
lib.rs

1//! # Stream Sequence Watcher
2//!
3//! Includes a pair of structures, [SequenceWatcher] and [SequenceWatchers]. They monitor a stream
4//! of data looking for a specific sequence of values.
5//!
6//! The original purpose for this crate was to monitor bytes of data recieved from stdin for a
7//! specific sequence that indicated that the input thread should shut down. Originally, only a
8//! single sequence was monitored for, but I added a simple way to look for multiple sequences
9//! simultaneously.
10//!
11//! # Examples
12//!
13//! ## Intended Behavior and Limitations
14//!
15//! * [SequenceWatcher] and [SequenceWatchers] both continue monitoring the stream after a check
16//!   returns true. For example, looking for the sequence (A, A), would return false, true, true
17//!   when given the input (A, A, A).
18//!
19//! ```
20//! use seq_watcher::SequenceWatchers;
21//!
22//! let test_stream = vec![
23//!     ('A', false),
24//!     ('A', false),
25//!     ('A', true),    // Matches AAA
26//!     ('A', true),    // Matches AAA
27//!     ('B', false),
28//!     ('A', true),    // Matches ABA
29//!     ('B', false),
30//!     ('A', true),    // Matches ABA
31//!     ('A', false),
32//!     ('A', true),    // Matches AAA
33//!     ('C', true),    // Matches C
34//! ];
35//!
36//! let watchers = SequenceWatchers::new(&[&['A', 'A', 'A'], &['A', 'B', 'A'], &['C']]);
37//!
38//! for (ch, expect) in test_stream {
39//!     assert_eq!(watchers.check(&ch), expect);
40//! }
41//!
42//! ```
43//!
44//! [SequenceWatcher] and [SequenceWatchers] that are given empty sequences always return false.
45//!
46//! ```
47//! # use seq_watcher::SequenceWatchers;
48//! let mut watcher = SequenceWatchers::new(&[]);  // Create empty watchers.
49//! let mut watchers = SequenceWatchers::new(&[]);  // Create empty watchers.
50//! let mut all_bytes = Vec::with_capacity(256);
51//! for b in 0..=u8::MAX {
52//!     assert_eq!(watcher.check(&b), false);   // With no sequence, all checks are false.
53//!     assert_eq!(watchers.check(&b), false);  // With no sequences, all checks are false.
54//!     all_bytes.push(b);                      // Generate sequence with all bytes.
55//! }
56//! watchers.add(&[]);          // Add of empty sequence does nothing.
57//! watchers.add(&all_bytes);   // Add sequuence with all bytes.
58//! for b in 0..u8::MAX {
59//!     assert_eq!(watchers.check(&b), false);   // Until sequence recieves the last byte, false.
60//! }
61//! assert_eq!(watchers.check(&u8::MAX), true); // With last byte in sequence, returns true.
62//! ```
63//!
64//! * Datatypes compatible are slightly more restrictive for [SequenceWatchers] than for
65//!   [SequenceWatcher]. [SequenceWatchers] requires the datatype to be [Eq], wheras
66//!   [SequenceWatcher] only needs [PartialEq].
67//!
68//! Float types are [PartialEq] but not [Eq].
69//!
70//! ```compile_fail
71//! # use seq_watcher::SequenceWatchers;
72//! let watchers = SequenceWatchers::new(&[0.0]);   // Float values are not Eq
73//! ```
74//!
75//! ```
76//! # use seq_watcher::SequenceWatcher;
77//! let watcher = SequenceWatcher::new(&[0.0]);     // Float values are PartialEq.
78//! ```
79//!
80//! # Performance
81//!
82//! The [SequenceWatcher] structure is resonably performant, but the [SequenceWatchers] structure
83//! needs work. [SequenceWatchers] is currently implemented as a [HashMap] of [SequenceWatcher]
84//! structures, but it would be better implemented with some sort of multi-state-aware trie.
85//! [SequenceWatchers] was created as an afterthought, since I mainly needed the [SequenceWatcher]
86//! for another project.
87use std::{
88    cell::Cell,
89    collections::HashMap,
90    fmt::Debug,
91    hash::Hash,
92};
93
94/// Monitors a stream of data for multiple sequences of data items.
95///
96/// # Examples
97///
98/// ```
99/// use seq_watcher::SequenceWatchers;
100///
101/// const CTRL_C: u8 = 3;
102/// const CTRL_D: u8 = 4;
103///
104/// // Watch the input stream for two consecutive <CTRL-C> characters.
105/// let watchers = SequenceWatchers::new(&[&[CTRL_C, CTRL_C], &[CTRL_C, CTRL_D]]);
106///
107/// for b in b'a'..=b'z' {
108///     assert_eq!(false, watchers.check(&b));   // Send single ASCII byte
109///     assert_eq!(false, watchers.check(&CTRL_C));   // Send single <Ctrl-C>
110/// }
111/// assert_eq!(true, watchers.check(&CTRL_C));    // Send a second <Ctrl-C>
112/// assert_eq!(true, watchers.check(&CTRL_D));    // Send a <Ctrl-D>
113/// ```
114#[derive(Debug)]
115pub struct SequenceWatchers<T>
116where
117    T: Eq + Clone + Debug + Hash,
118{
119    watchers: HashMap<Vec<T>, SequenceWatcher<T>>,
120}
121
122impl<T: Eq + Clone + Debug + Hash> SequenceWatchers<T> {
123    /// Create a new [SequenceWatchers] from a slice of slices of data. The data type can be
124    /// anything with [Eq], [Debug], and [Clone] traits.
125    ///
126    /// Internally, the [SequenceWatchers] structure contains a vector of [SequenceWatcher]
127    /// structures.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// # use seq_watcher::SequenceWatchers;
133    /// let watchers = SequenceWatchers::new(&[&['q'], &['Q']]);
134    ///
135    /// assert_eq!(true, watchers.check(&'q'));
136    /// assert_eq!(true, watchers.check(&'Q'));
137    /// ```
138    pub fn new(sequences: &[&[T]]) -> Self {
139        let mut watchers = Self { watchers: HashMap::with_capacity(sequences.len()) };
140        for seq in sequences {
141            watchers.add(seq);
142        }
143        watchers
144    }
145
146    /// Tells the [SequenceWatchers] of a new input item and checks to see if a sequence has been
147    /// completed. Returns true when a sequence is completed.
148    ///
149    /// # Examples
150    ///
151    /// ```
152    /// # use seq_watcher::SequenceWatchers;
153    /// let watchers = SequenceWatchers::new(&[&[false, true], &[false, true, true]]);
154    ///
155    /// assert_eq!(false, watchers.check(&true));
156    /// assert_eq!(false, watchers.check(&false));
157    /// assert_eq!(true, watchers.check(&true));    // Matches first sequence
158    /// assert_eq!(true, watchers.check(&true));    // Matches second sequence
159    /// ```
160    pub fn check(&self, value: &T) -> bool {
161        let mut result = false;
162        for watcher in self.watchers.values() {
163            if watcher.check(value) {
164                result = true;
165            }
166        }
167        result
168    }
169
170    /// Adds a new [SequenceWatcher] to the [SequenceWatchers]. If the sequence matches a
171    /// pre-existing [SequenceWatcher], it does nothing.
172    ///
173    /// # Examples
174    ///
175    /// ```
176    /// # use seq_watcher::SequenceWatchers;
177    /// let mut watchers = SequenceWatchers::new(&[]);
178    /// watchers.add(&[]);  // This does nothing.
179    /// watchers.add(&[false, true]);
180    /// watchers.add(&[false, true, true]);
181    ///
182    /// assert_eq!(false, watchers.check(&true));
183    /// assert_eq!(false, watchers.check(&false));
184    /// assert_eq!(true, watchers.check(&true));    // Matches first sequence
185    /// assert_eq!(true, watchers.check(&true));    // Matches second sequence
186    /// ```
187    pub fn add(&mut self, new_seq: &[T]) {
188        if !new_seq.is_empty() && !self.watchers.contains_key(new_seq) {
189            self.watchers.insert(new_seq.to_vec(), SequenceWatcher::new(new_seq));
190        }
191    }
192
193    /// Removes a sequence watcher for a given sequence. It returns the removed [SequenceWatcher].
194    ///
195    /// # Examples
196    ///
197    /// ```
198    /// # use seq_watcher::SequenceWatchers;
199    /// let mut watchers = SequenceWatchers::new(&[&[false, true], &[false, true, true]]);
200    /// watchers.remove(&[false, true, true]);
201    ///
202    /// assert_eq!(false, watchers.check(&true));
203    /// assert_eq!(false, watchers.check(&false));
204    /// assert_eq!(true, watchers.check(&true));    // Matches first sequence
205    /// assert_eq!(false, watchers.check(&true));   // Matches second sequence, which was removed
206    /// ```
207    pub fn remove(&mut self, seq: &[T]) -> Option<SequenceWatcher<T>> {
208        self.watchers.remove(seq)
209    }
210
211    /// Returns the number of sequences being monitored.
212    ///
213    /// # Examples
214    ///
215    /// ```
216    /// # use seq_watcher::SequenceWatchers;
217    /// let watchers = SequenceWatchers::new(&[&['A'], &['B'], &['C'], &['D']]);
218    ///
219    /// assert_eq!(4, watchers.len());
220    /// ```
221    pub fn len(&self) -> usize {
222        self.watchers.len()
223    }
224
225    /// Returns an iterator over the sequences being monitored by the [SequenceWatchers].
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// # use seq_watcher::SequenceWatchers;
231    /// let watchers = SequenceWatchers::new(&[&[false, true], &[false, true, true]]);
232    ///
233    /// let mut sequences: Vec<&Vec<bool>> = watchers.sequences().collect();
234    /// sequences.sort();   // Make sure keys are sorted.
235    /// let mut sequences = sequences.into_iter();
236    /// assert_eq!(sequences.next(), Some(&vec![false, true]));
237    /// assert_eq!(sequences.next(), Some(&vec![false, true, true]));
238    /// assert_eq!(sequences.next(), None);
239    /// ```
240    pub fn sequences(&self) -> std::collections::hash_map::Keys<Vec<T>, SequenceWatcher<T>> {
241        self.watchers.keys()
242    }
243}
244
245/// Monitors a stream of data for a sequence.
246///
247/// # Examples
248///
249/// ```
250/// use seq_watcher::SequenceWatcher;
251///
252/// const CTRL_C: u8 = 3;
253///
254/// // Watch the input stream for two consecutive <CTRL-C> characters.
255/// let watcher = SequenceWatcher::new(&[CTRL_C, CTRL_C]);
256///
257/// for b in b'a'..=b'z' {
258///     assert_eq!(false, watcher.check(&b));   // Send single ASCII byte
259///     assert_eq!(false, watcher.check(&CTRL_C));   // Send single <Ctrl-C>
260/// }
261/// assert_eq!(true, watcher.check(&CTRL_C));    // Send a second <Ctrl-C>
262/// ```
263#[derive(Clone, Debug)]
264pub struct SequenceWatcher<T>
265where
266    T: PartialEq + Clone + Debug,
267{
268    sequence: Vec<T>,
269    index: Cell<usize>,
270}
271
272impl<T: PartialEq + Clone + Debug> SequenceWatcher<T> {
273    /// Create a new [SequenceWatcher] from a slice of data. The data type can be anything with
274    /// [PartialEq], [Debug], and [Clone] traits.
275    ///
276    /// Internally, the [SequenceWatcher] structure contains a vector of the sequence it monitors
277    /// and an index indicating where in the sequence it is expecting next.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// # use seq_watcher::SequenceWatcher;
283    /// let watcher = SequenceWatcher::new(&['q', 'u', 'i', 't']);
284    ///
285    /// assert_eq!(false, watcher.check(&'q'));
286    /// assert_eq!(false, watcher.check(&'u'));
287    /// assert_eq!(false, watcher.check(&'i'));
288    /// assert_eq!(true, watcher.check(&'t'));
289    /// ```
290    ///
291    /// # Panics
292    ///
293    /// [`SequenceWatcher::new`] will panic if the sequence slice is empty.
294    pub fn new(seq: &[T]) -> Self {
295        Self {
296            sequence: seq.to_vec(),
297            index: Cell::new(0),
298        }
299    }
300
301    /// Tells the [SequenceWatcher] of a new input item and checks to see if a sequence has been
302    /// completed. Returns true when the sequence is completed.
303    ///
304    /// # Examples
305    ///
306    /// ```
307    /// # use seq_watcher::SequenceWatcher;
308    /// let watcher = SequenceWatcher::new(&[Some("found")]);
309    ///
310    /// assert_eq!(false, watcher.check(&None));
311    /// assert_eq!(false, watcher.check(&Some("something")));
312    /// assert_eq!(false, watcher.check(&Some("anything")));
313    /// assert_eq!(true, watcher.check(&Some("found")));
314    /// ```
315    pub fn check(&self, value: &T) -> bool {
316        if self.sequence.is_empty() { return false; }
317        self.witness(value);
318        if self.sequence.len() == self.index.get() {
319            self.on_mismatch(&self.sequence[1..]);
320            true
321        }
322        else {
323            false
324        }
325    }
326
327    /// Returns the a reference to the data value that the [SequenceWatcher] is expecting next.
328    ///
329    /// # Examples
330    ///
331    /// ```
332    /// # use seq_watcher::SequenceWatcher;
333    /// let watcher = SequenceWatcher::new(&[1, 2]);
334    ///
335    /// assert_eq!(1, *watcher.expects());
336    /// assert_eq!(false, watcher.check(&0));
337    /// assert_eq!(1, *watcher.expects());
338    /// assert_eq!(false, watcher.check(&1));
339    /// assert_eq!(2, *watcher.expects());
340    /// assert_eq!(true, watcher.check(&2));
341    /// assert_eq!(1, *watcher.expects());
342    /// ```
343    pub fn expects(&self) -> &T {
344        &self.sequence[self.index.get()]
345    }
346
347    /// Returns the index in the sequence that the [SequenceWatcher] is expecting next. The index
348    /// will never be greater than or equal to the sequence length.
349    ///
350    /// # Examples
351    ///
352    /// ```
353    /// # use seq_watcher::SequenceWatcher;
354    /// let watcher = SequenceWatcher::new(&[1, 2]);
355    ///
356    /// assert_eq!(0, watcher.index());
357    /// assert_eq!(false, watcher.check(&0));
358    /// assert_eq!(0, watcher.index());
359    /// assert_eq!(false, watcher.check(&1));
360    /// assert_eq!(1, watcher.index());
361    /// assert_eq!(true, watcher.check(&2));
362    /// assert_eq!(0, watcher.index());
363    /// ```
364    #[inline]
365    pub fn index(&self) -> usize {
366        self.index.get()
367    }
368
369    /// Resets the [SequenceWatcher] so it doesn't remember if it has seen any protions of the
370    /// sequence.
371    ///
372    /// # Examples
373    ///
374    /// ```
375    /// # use seq_watcher::SequenceWatcher;
376    /// let watcher = SequenceWatcher::new(&[1, 2]);
377    ///
378    /// assert_eq!(false, watcher.check(&1));
379    /// assert_eq!(1, watcher.index());
380    /// watcher.reset();
381    /// assert_eq!(false, watcher.check(&2));
382    /// assert_eq!(false, watcher.check(&1));
383    /// assert_eq!(true, watcher.check(&2));
384    /// ```
385    pub fn reset(&self) {
386        self.index.set(0);
387    }
388
389    /// Returns a reference to the sequence.
390    ///
391    /// # Examples
392    ///
393    /// ```
394    /// # use seq_watcher::SequenceWatcher;
395    /// let watcher = SequenceWatcher::new(&[Ok(()), Err(())]);
396    ///
397    /// assert_eq!(&[Ok(()), Err(())], watcher.sequence());
398    /// ```
399    pub fn sequence(&self) -> &[T] {
400        &self.sequence[..]
401    }
402
403    /// Returns the length of the sequence.
404    ///
405    /// # Examples
406    ///
407    /// ```
408    /// # use seq_watcher::SequenceWatcher;
409    /// let watcher = SequenceWatcher::new(&[false, true, false, true]);
410    ///
411    /// assert_eq!(4, watcher.len());
412    /// ```
413    pub fn len(&self) -> usize {
414        self.sequence.len()
415    }
416
417    // Internal function that does all of the work of monitoring a new data type, but doesn't check
418    // to see if it has successfully reached the end of the sequence. This shouldn't be a public
419    // interface because it can leave the watcher in an invalid state (i.e. watchers should always
420    // be able to accept new input data, but this can leave the index pointing past the end of the
421    // vector.
422    fn witness(&self, value: &T) {
423        if self.sequence.is_empty() { return; }
424        if *value == self.sequence[self.index.get()] {
425            self.index.set(self.index.get() + 1);
426        }
427        else {
428            match self.index.get() {
429                0 => {},
430                1 => {
431                    self.index.set(0);
432                    self.witness(value)
433                },
434                _ => {
435                    self.on_mismatch(&self.sequence[1..self.index.get()]);
436                    self.witness(value)
437                },
438            }
439        }
440    }
441
442    // Internal function that is given a subset of the sequence that it resends to itself after
443    // resetting the index to 0.
444    fn on_mismatch(&self, retry: &[T]) {
445        self.index.set(0);
446        for value in retry {
447            self.witness(value);
448            // I am a little concerned about a recursive loop since witness calls on_mismatch, but
449            // I think it will be fine since the data sets that they retry are always decreasing.
450            // I'll try to think of a sequence that will exercise this.
451        }
452    }
453}
454
455/// Creates a new [SequenceWatcher] from a [Vec].
456///
457/// # Examples
458///
459/// ```
460/// # use seq_watcher::SequenceWatcher;
461/// let seq = vec![b'X'];
462/// let watcher = SequenceWatcher::from(seq);
463///
464/// assert_eq!(true, watcher.check(&b'X'));
465/// ```
466impl<T: PartialEq + Debug + Clone> From<Vec<T>> for SequenceWatcher<T> {
467    fn from(src: Vec<T>) -> Self {
468        Self {
469            sequence: src,
470            index: Cell::new(0),
471        }
472    }
473}
474
475/// Creates a new [SequenceWatcher] from a slice.
476///
477/// # Examples
478///
479/// ```
480/// # use seq_watcher::SequenceWatcher;
481/// let watcher = SequenceWatcher::from(&[b'X'][..]);   // This is treated as a slice.
482///
483/// assert_eq!(true, watcher.check(&b'X'));
484/// ```
485///
486/// This also works for array references for arrays of up to 32 itmes.
487///
488/// ```
489/// # use seq_watcher::SequenceWatcher;
490/// let watcher = SequenceWatcher::from(&[b'X']);   // This is treated as an array reference.
491///
492/// assert_eq!(true, watcher.check(&b'X'));
493/// ```
494///
495/// There is no support for a zero length array reference, so when using the array version, it will
496/// fail to compile.
497///
498/// ```compile_fail
499/// # use seq_watcher::SequenceWatcher;
500/// let watcher: SequenceWatcher<u8> = SequenceWatcher::from(&[]);
501/// ```
502impl<T: PartialEq + Debug + Clone> From<&[T]> for SequenceWatcher<T> {
503    fn from(src: &[T]) -> Self {
504        SequenceWatcher::new(src)
505    }
506}
507
508macro_rules! from_array {
509    ($($s:expr),*) => {
510        $(
511            /// Creates a new [SequenceWatcher] from an array.
512            impl<T: PartialEq + Debug + Clone> From<&[T; $s]> for SequenceWatcher<T> {
513                fn from(src: &[T; $s]) -> Self {
514                    Self::from(&src[..])
515                }
516            }
517        )*
518    }
519}
520
521from_array!(
522    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
523    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
524);
525
526#[cfg(test)]
527mod tests {
528    use std::{
529        fmt::Debug,
530    };
531    use proptest::{
532        prelude::*,
533        sample::SizeRange,
534    };
535    use crate::{SequenceWatcher, SequenceWatchers};
536
537    #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
538    enum ByteOrChar {
539        Byte(u8),
540        Char(char),
541    }
542
543    impl From<u8> for ByteOrChar {
544        fn from(src: u8) -> Self {
545            ByteOrChar::Byte(src)
546        }
547    }
548
549    impl From<char> for ByteOrChar {
550        fn from(src: char) -> Self {
551            if 1 == src.len_utf8() {
552                ByteOrChar::Byte(src as u8)
553            }
554            else {
555                ByteOrChar::Char(src)
556            }
557        }
558    }
559
560    // Takes a sequence vector and a stream vector and returns the sequence vector and a
561    // stream vector that is guaranteed to succeed on the last value.
562    //
563    // It verifies that there are no instances of the sequence vector in the stream vector, and
564    // then appends the sequence vector to the stream vector and returns the original sequence
565    // vector and an updated sequence vector.
566    fn values_and_stream<T: Eq + Clone + Debug>(sequence: Vec<T>, mut stream: Vec<T>) -> (Vec<T>, Vec<T>) {
567        let seq_len = sequence.len();
568        let mut i = 0;
569        stream.extend_from_slice(&sequence);
570        let mut not_good = true;
571        while not_good {
572            while (i + seq_len) < stream.len() {
573                if &sequence[..] == &stream[i..(i+seq_len)] {
574                    if i + seq_len + seq_len <= stream.len() {
575                        // If we are not to the final sequence, remove the last element.
576                        stream.remove(i+seq_len-1);
577                    }
578                    else {
579                        // If we are overlapping the final sequence, then remove the first value.
580                        stream.remove(i);
581                        // Since we remove the first value, we may inadvertently be creating a valid
582                        // sequence with the previous value, so we need to recheck the index before.
583                        if 0 < i { i -= 1; }    // If the current index is not 0.
584                    }
585                }
586                else {
587                    // Otherwise, move to the next sub-vector.
588                    i += 1;
589                }
590            }
591            // On a rare occasion, this will accidentally create a duplicate sequence earlier than
592            // it can otherwise detect, so we do a final samity check and check to see if we find
593            // any early sequences, and if we do, we restart the filter.
594            not_good = false;   // We start with the assumption that this will be okay.
595            if stream.len() > seq_len {
596                for x in 0..(stream.len()-1-seq_len) {
597                    if &sequence[..] == &stream[x..(x+seq_len)] {
598                        not_good = true;    // Oops. We found a match
599                        i = 0;
600                    }
601                }
602            }
603        }
604        // Now, add the correct sequence to the end so that it will always succed on the last byte.
605        (sequence, stream)
606    }
607
608    // This makes sure that the values_and_stream function always returns the sequence only at the
609    // end.
610    #[test]
611    fn test_values_and_stream_test_function() {
612        {
613            let (find, stream) = values_and_stream(vec![b'a', b'a'], vec![b'a']);
614            test_seq_watcher(&find, &stream).unwrap();
615        }
616        {
617            let (find, stream) = values_and_stream(vec![b'a', b'b', b'a'], vec![b'b', b'a', b'b', b'a']);
618            test_seq_watcher(&find, &stream).unwrap();
619        }
620    }
621
622    // Takes a sequence slice and a stream slice and verifies that a Sequence Watcher with the
623    // sequence only succeeds on the last value in the stream slice.
624    fn test_seq_watcher<T: PartialEq + Clone + Debug>(sequence: &[T], stream: &[T]) -> Result<(), proptest::test_runner::TestCaseError> {
625        prop_assert!(0 < stream.len(), "Invalid stream: {:?}", stream);
626        prop_assert!(0 < sequence.len(), "Invalid sequence: {:?}", sequence);
627        let watcher = SequenceWatcher::new(sequence);
628        let last_index = stream.len() - 1;
629        for i in 0..last_index {
630            prop_assert_eq!(false, watcher.check(&stream[i]));
631        }
632        prop_assert_eq!(true, watcher.check(&stream[last_index]));
633        Ok(())
634    }
635
636    prop_compose! {
637        fn byte_vec(range: impl Into<SizeRange>)(v in prop::collection::vec(0..u8::MAX, range)) -> Vec<u8> { v }
638    }
639
640    prop_compose! {
641        fn char_vec(range: impl Into<SizeRange>)(v in prop::collection::vec(proptest::char::any(), range)) -> Vec<char> { v }
642    }
643
644    prop_compose! {
645        fn byte_or_char_vec(range: impl Into<SizeRange>)(v in char_vec(range)) -> Vec<ByteOrChar> {
646            let v: Vec<ByteOrChar> = v.into_iter().map(|bc| {ByteOrChar::from(bc)}).collect();
647            v
648        }
649    }
650
651    prop_compose! {
652        fn bool_vec(range: impl Into<SizeRange>)(v in prop::collection::vec(proptest::bool::ANY, range)) -> Vec<bool> { v }
653    }
654
655    prop_compose! {
656        fn chars_and_stream()(seq in char_vec(1..10), v in char_vec(10..50)) -> (Vec<char>, Vec<char>)
657        {
658            values_and_stream(seq, v)
659        }
660    }
661
662    prop_compose! {
663        fn bytes_and_stream()(seq in byte_vec(1..10), v in byte_vec(10..50)) -> (Vec<u8>, Vec<u8>)
664        {
665            values_and_stream(seq, v)
666        }
667    }
668
669    prop_compose! {
670        fn byte_or_chars_and_stream()(seq in byte_or_char_vec(1..10), v in byte_or_char_vec(10..50)) -> (Vec<ByteOrChar>, Vec<ByteOrChar>)
671        {
672            values_and_stream(seq, v)
673        }
674    }
675
676    prop_compose! {
677        fn bools_and_stream()(seq in bool_vec(1..10), v in bool_vec(10..50)) -> (Vec<bool>, Vec<bool>)
678        {
679            values_and_stream(seq, v)
680        }
681    }
682
683    proptest! {
684        #[test]
685        fn test_chars_sequence((find, stream) in chars_and_stream()) {
686            test_seq_watcher(&find[..], &stream[..])?;
687        }
688    }
689
690    proptest! {
691        #[test]
692        fn test_bytes_sequence((find, stream) in bytes_and_stream()) {
693            test_seq_watcher(&find[..], &stream[..])?;
694        }
695    }
696
697    proptest! {
698        #[test]
699        fn test_byte_or_chars_sequence((find, stream) in byte_or_chars_and_stream()) {
700            test_seq_watcher(&find[..], &stream[..])?;
701        }
702    }
703
704    proptest! {
705        #[test]
706        fn test_bools_sequence((find, stream) in bools_and_stream()) {
707            test_seq_watcher(&find[..], &stream[..])?;
708        }
709    }
710
711    #[test]
712    fn empty_char_sequence_watcher_always_false() {
713        let watcher = SequenceWatcher::new(&[]);
714        assert_eq!(false, watcher.check(&'a'));
715    }
716
717    #[test]
718    fn empty_byte_sequence_watcher_always_false() {
719        let watcher = SequenceWatcher::new(&[]);
720        assert_eq!(false, watcher.check(&b'a'));
721    }
722
723    #[test]
724    fn empty_byte_or_char_sequence_watcher_always_false() {
725        let watcher = SequenceWatcher::new(&[]);
726        assert_eq!(false, watcher.check(&'a'));
727    }
728
729    proptest! {
730        #[test]
731        fn empty_char_sequence_is_always_false(stream in char_vec(10..20)) {
732            let watchers = SequenceWatchers::new(&[]);
733            for c in stream {
734                prop_assert_eq!(false, watchers.check(&c));
735            }
736        }
737    }
738
739    proptest! {
740        #[test]
741        fn empty_byte_sequence_is_always_false(stream in byte_vec(10..20)) {
742            let watchers = SequenceWatchers::new(&[]);
743            for b in stream {
744                prop_assert_eq!(false, watchers.check(&b));
745            }
746        }
747    }
748
749    proptest! {
750        #[test]
751        fn empty_byte_or_char_sequence_is_always_false(stream in byte_or_char_vec(10..20)) {
752            let watchers = SequenceWatchers::new(&[]);
753            for c in stream {
754                prop_assert_eq!(false, watchers.check(&c));
755            }
756        }
757    }
758
759    #[test]
760    fn test_specific_patterns() {   // And also some different types.
761        // This will fail if we just discard the state on a mismatch. On a failing case, when it
762        // hits the second zero in the stream, it forgets about both zeroes and then doesn't match
763        // the 1 because it is expecting a zero first.
764        test_seq_watcher(&[false, true], &[false, false, true]).expect("Failed specific test pattern 1");
765        // Let's say that we are smarter and pass the first test by retrying the current character
766        // after resetting the index. what happens if we need a partial reset.
767        test_seq_watcher(&[0u64, 0, 1], &[0, 0, 0, 1]).expect("Failed specific test pattern 2");
768        // Now we need a pattern that will cause the simple fix for the second test to fail (or
769        // maybe I don't need the more complicated solution).
770        test_seq_watcher(&["F", "T", "F", "F", "F"],
771            &["F", "T", "F", "F", "T", "F", "F", "F"]).expect("Failed specific test pattern 3");
772        // Now we'll just repeat the last pattern with some alternate types.
773        test_seq_watcher(&[None, Some(0.0), None, None, None],
774            &[None, Some(0.0), None, None, Some(0.0), None, None, None])
775            .expect("Failed specific test pattern 4");
776        test_seq_watcher(&[Err(()), Ok(()), Err(()), Err(()), Err(())],
777            &[Err(()), Ok(()), Err(()), Err(()), Ok(()), Err(()), Err(()), Err(())])
778            .expect("Failed specific test pattern 5");
779    }
780}