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}