slippery_iter/
lib.rs

1#![allow(incomplete_features)]
2#![feature(generic_const_exprs, box_patterns)]
3use std::{fmt, marker::PhantomData, str::Chars};
4
5#[derive(Clone, Debug)]
6pub struct SlipperyIter<'a, I>
7where
8  I: Iterator + Sized,
9  I::Item: Clone + fmt::Debug + 'a,
10{
11  offset: usize,
12  inner: Box<[I::Item]>,
13  _marker: PhantomData<&'a [I::Item]>,
14}
15
16#[derive(Clone, Debug)]
17pub struct SlipperyCharsIter<'a> {
18  inner: SlipperyIter<'a, Chars<'a>>,
19  pub line: usize,
20  pub column: usize,
21  line_queue: Vec<usize>,
22  column_queue: Vec<usize>,
23}
24
25impl<I> From<I> for SlipperyIter<'_, I>
26where
27  I: Iterator + Clone,
28  I::Item: Clone + fmt::Debug,
29{
30  fn from(iter: I) -> Self {
31    Self {
32      offset: 0,
33      inner: iter.clone().collect::<Vec<_>>().into(),
34      _marker: PhantomData,
35    }
36  }
37}
38
39impl<'a> From<Chars<'a>> for SlipperyCharsIter<'a> {
40  fn from(iter: Chars<'a>) -> Self {
41    let mut self_ = Self {
42      inner: iter.slippery(),
43      line: 0,
44      column: 0,
45      line_queue: Vec::new(),
46      column_queue: Vec::new(),
47    };
48    self_.line_queue.reserve(16);
49    self_.column_queue.reserve(16);
50    self_
51  }
52}
53
54pub trait IntoSlipperyIterator<'a>: IntoIterator {
55  type Item;
56  type IntoSlipperyIter: Iterator<Item = <Self as IntoSlipperyIterator<'a>>::Item> + 'a;
57
58  fn into_slippery_iter(self) -> Self::IntoSlipperyIter;
59}
60
61pub trait IntoSlipperyCharsIterator<'a>: IntoIterator {
62  fn into_slippery_chars_iter(self) -> SlipperyCharsIter<'a>;
63}
64
65impl<'a, I: 'a, T> IntoSlipperyIterator<'a> for T
66where
67  T: IntoIterator<Item = I> + Clone + 'a,
68  T::Item: Clone + fmt::Debug,
69  T::IntoIter: Clone,
70{
71  type Item = T::Item;
72  type IntoSlipperyIter = SlipperyIter<'a, T::IntoIter>;
73
74  fn into_slippery_iter(self) -> Self::IntoSlipperyIter {
75    SlipperyIter::<'a>::from(self.into_iter())
76  }
77}
78
79impl<'a> IntoSlipperyCharsIterator<'a> for Chars<'a> {
80  fn into_slippery_chars_iter(self) -> SlipperyCharsIter<'a> {
81    SlipperyCharsIter::<'a>::from(self)
82  }
83}
84
85pub trait SlipperyIterator<'a>: Iterator
86where
87  Self: Sized,
88  <Self as Iterator>::Item: Clone + fmt::Debug,
89{
90  type Item;
91
92  fn slippery(self) -> SlipperyIter<'a, Self>;
93}
94
95#[allow(dead_code)]
96pub trait SlipperyCharsIterator<'a> {
97  fn slippery_chars(self) -> SlipperyCharsIter<'a>;
98}
99
100impl<'a, T> SlipperyIterator<'a> for T
101where
102  T: Iterator + Clone + Sized + 'a,
103  T::Item: Clone + fmt::Debug,
104{
105  type Item = T::Item;
106
107  fn slippery(self) -> SlipperyIter<'a, Self> {
108    self.into_slippery_iter()
109  }
110}
111
112impl<'a> SlipperyCharsIterator<'a> for &'a str {
113  fn slippery_chars(self) -> SlipperyCharsIter<'a> {
114    self.chars().into_slippery_chars_iter()
115  }
116}
117
118impl<I, T> Iterator for SlipperyIter<'_, I>
119where
120  I: Iterator<Item = T> + Clone,
121  I::Item: Clone + fmt::Debug,
122{
123  type Item = <I as Iterator>::Item;
124
125  fn next(&mut self) -> Option<<Self as Iterator>::Item> {
126    self.consume()
127  }
128}
129
130impl Iterator for SlipperyCharsIter<'_> {
131  type Item = char;
132
133  fn next(&mut self) -> Option<char> {
134    match self.consume() {
135      '\0' => None,
136      x => Some(x),
137    }
138  }
139}
140
141#[allow(dead_code)]
142impl<I, T> SlipperyIter<'_, I>
143where
144  I: Iterator<Item = T>,
145  I::Item: Clone + fmt::Debug,
146{
147  pub fn peek_forward(&self) -> Option<I::Item> {
148    self.peek_forward_many::<1>().first()?.clone()
149  }
150
151  pub fn peek_forward_many<const AMOUNT: usize>(&self) -> Box<[Option<I::Item>]> {
152    let (mut v, mut o) = (Vec::new(), self.offset);
153    for _ in 0..AMOUNT {
154      if o >= self.inner.len() || o >= usize::MAX - 1 {
155        v.push(None);
156      } else {
157        v.push(Some(self.inner[o].clone()));
158        o = o.saturating_add(1);
159      }
160    }
161    v.into_boxed_slice()
162  }
163
164  pub fn peek_backward(&self) -> Option<I::Item> {
165    self.peek_backward_many::<1>().first()?.clone()
166  }
167
168  pub fn peek_backward_many<const AMOUNT: usize>(&self) -> Box<[Option<I::Item>]> {
169    let (mut v, mut o) = (Vec::new(), self.offset.saturating_sub(1));
170    for _ in 0..AMOUNT {
171      let x = &self.inner[o];
172      o = o.saturating_sub(1);
173      v.push(Some(x.clone()));
174    }
175    v.into_boxed_slice()
176  }
177
178  fn look_around<const AMOUNT: usize, const L: isize, const DIR: bool>(
179    &self,
180  ) -> Box<[Option<I::Item>]>
181  where
182    [(); AMOUNT + L.unsigned_abs()]: Sized,
183  {
184    match L.signum() {
185      -1 => match DIR {
186        true => {
187          let mut v = self.peek_backward_many::<{ L.unsigned_abs() }>().to_vec();
188          v.extend(self.peek_forward_many::<AMOUNT>());
189          v.into_boxed_slice()
190        }
191        false => self.peek_backward_many::<{ AMOUNT + L.unsigned_abs() }>(),
192      },
193      1 => match DIR {
194        false => {
195          let mut v = self.peek_backward_many::<{ L.unsigned_abs() }>().to_vec();
196          v.extend(self.peek_forward_many::<AMOUNT>());
197          v.into_boxed_slice()
198        }
199        true => self.peek_forward_many::<{ AMOUNT + L.unsigned_abs() }>(),
200      },
201      0 | _ => match DIR {
202        true => self.peek_forward_many::<AMOUNT>(),
203        false => self.peek_backward_many::<AMOUNT>(),
204      },
205    }
206  }
207
208  pub fn consume(&mut self) -> Option<I::Item> {
209    self.consume_many::<1, 0>().first()?.clone()
210  }
211
212  pub fn consume_if<F>(&mut self, predicate: F) -> Option<I::Item>
213  where
214    F: FnOnce(Option<I::Item>) -> bool,
215  {
216    self
217      .consume_many_if::<_, 1, 0>(|mut v| predicate(v.remove(0)))
218      .first()?
219      .clone()
220  }
221
222  pub fn consume_if_then<F1, F2>(&mut self, predicate: F1, action: F2) -> Option<I::Item>
223  where
224    F1: FnOnce(Option<I::Item>) -> bool,
225    F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
226  {
227    self.consume_if_then_else::<F1, F2, _>(predicate, action, || {})
228  }
229
230  pub fn consume_if_then_else<F1, F2, F3>(
231    &mut self,
232    predicate: F1,
233    action: F2,
234    action_else: F3,
235  ) -> Option<I::Item>
236  where
237    F1: FnOnce(Option<I::Item>) -> bool,
238    F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
239    F3: FnOnce(),
240  {
241    self
242      .consume_many_if_then_else::<_, _, _, 1, 0>(
243        |v| {
244          predicate(match v.first() {
245            Some(&None) | None => None,
246            Some(Some(value)) => Some(value.clone()),
247          })
248        },
249        |bv| Box::new([action(bv.first().unwrap().clone())]),
250        action_else,
251      )
252      .first()?
253      .clone()
254  }
255
256  pub fn consume_many<const AMOUNT: usize, const L: isize>(&mut self) -> Box<[Option<I::Item>]>
257  where
258    [(); AMOUNT + L.unsigned_abs()]: Sized,
259  {
260    let v = self.look_around::<AMOUNT, L, true>();
261    self.offset = self.offset.saturating_add(AMOUNT);
262    v
263  }
264
265  pub fn consume_many_if<F, const AMOUNT: usize, const L: isize>(
266    &mut self,
267    predicate: F,
268  ) -> Box<[Option<I::Item>]>
269  where
270    F: FnOnce(Vec<Option<I::Item>>) -> bool,
271    [(); AMOUNT + L.unsigned_abs()]: Sized,
272  {
273    if predicate(self.look_around::<AMOUNT, L, true>().to_vec()) {
274      self.consume_many::<AMOUNT, L>()
275    } else {
276      Box::new([])
277    }
278  }
279
280  pub fn consume_many_if_then<F1, F2, const AMOUNT: usize, const L: isize>(
281    &mut self,
282    predicate: F1,
283    action: F2,
284  ) -> Box<[Option<I::Item>]>
285  where
286    F1: FnOnce(Vec<Option<I::Item>>) -> bool,
287    F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
288    [(); AMOUNT + L.unsigned_abs()]: Sized,
289  {
290    self.consume_many_if_then_else::<F1, F2, _, AMOUNT, L>(predicate, action, || {})
291  }
292
293  pub fn consume_many_if_then_else<F1, F2, F3, const AMOUNT: usize, const L: isize>(
294    &mut self,
295    predicate: F1,
296    action: F2,
297    action_else: F3,
298  ) -> Box<[Option<I::Item>]>
299  where
300    F1: FnOnce(Vec<Option<I::Item>>) -> bool,
301    F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
302    F3: FnOnce(),
303    [(); AMOUNT + L.unsigned_abs()]: Sized,
304  {
305    match self.consume_many_if::<_, AMOUNT, L>(predicate) {
306      x @ box [] => {
307        action_else();
308        x
309      }
310      y @ box [..] => action(y),
311    }
312  }
313
314  pub fn restore(&mut self) -> Option<I::Item> {
315    self.restore_many::<1, 0>().first()?.clone()
316  }
317
318  pub fn restore_if<F>(&mut self, predicate: F) -> Option<I::Item>
319  where
320    F: FnOnce(Option<I::Item>) -> bool,
321  {
322    self
323      .restore_many_if::<_, 1, 0>(|v| {
324        predicate(match v.first() {
325          Some(&None) | None => None,
326          Some(Some(value)) => Some(value.clone()),
327        })
328      })
329      .first()?
330      .clone()
331  }
332
333  pub fn restore_if_then<F1, F2>(&mut self, predicate: F1, action: F2) -> Option<I::Item>
334  where
335    F1: FnOnce(Option<I::Item>) -> bool,
336    F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
337  {
338    self.restore_if_then_else::<F1, F2, _>(predicate, action, || {})
339  }
340
341  pub fn restore_if_then_else<F1, F2, F3>(
342    &mut self,
343    predicate: F1,
344    action: F2,
345    action_else: F3,
346  ) -> Option<I::Item>
347  where
348    F1: FnOnce(Option<I::Item>) -> bool,
349    F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
350    F3: FnOnce(),
351  {
352    self
353      .restore_many_if_then_else::<_, _, _, 1, 0>(
354        |v| {
355          predicate(match v.first() {
356            Some(&None) | None => None,
357            Some(Some(value)) => Some(value.clone()),
358          })
359        },
360        |bv| Box::new([action(bv.first().unwrap().clone())]),
361        action_else,
362      )
363      .first()?
364      .clone()
365  }
366
367  pub fn restore_many<const AMOUNT: usize, const L: isize>(&mut self) -> Box<[Option<I::Item>]>
368  where
369    [(); AMOUNT + L.unsigned_abs()]: Sized,
370  {
371    let v = self.look_around::<AMOUNT, L, false>();
372    self.offset = self.offset.saturating_sub(AMOUNT);
373    v
374  }
375
376  pub fn restore_many_if<F, const AMOUNT: usize, const L: isize>(
377    &mut self,
378    predicate: F,
379  ) -> Box<[Option<I::Item>]>
380  where
381    F: FnOnce(Vec<Option<I::Item>>) -> bool,
382    [(); AMOUNT + L.unsigned_abs()]: Sized,
383  {
384    if predicate(self.look_around::<AMOUNT, L, false>().to_vec()) {
385      self.restore_many::<AMOUNT, L>()
386    } else {
387      Box::new([])
388    }
389  }
390
391  pub fn restore_many_if_then<F1, F2, const AMOUNT: usize, const L: isize>(
392    &mut self,
393    predicate: F1,
394    action: F2,
395  ) -> Box<[Option<I::Item>]>
396  where
397    F1: FnOnce(Vec<Option<I::Item>>) -> bool,
398    F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
399    [(); AMOUNT + L.unsigned_abs()]: Sized,
400  {
401    self.restore_many_if_then_else::<F1, F2, _, AMOUNT, L>(predicate, action, || {})
402  }
403
404  pub fn restore_many_if_then_else<F1, F2, F3, const AMOUNT: usize, const L: isize>(
405    &mut self,
406    predicate: F1,
407    action: F2,
408    action_else: F3,
409  ) -> Box<[Option<I::Item>]>
410  where
411    F1: FnOnce(Vec<Option<I::Item>>) -> bool,
412    F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
413    F3: FnOnce(),
414    [(); AMOUNT + L.unsigned_abs()]: Sized,
415  {
416    match self.restore_many_if::<_, AMOUNT, L>(predicate) {
417      x @ box [] => {
418        action_else();
419        x
420      }
421      y @ box [..] => action(y),
422    }
423  }
424}
425
426#[allow(dead_code)]
427impl SlipperyCharsIter<'_> {
428  pub fn position(&self) -> (usize, usize) {
429    (self.line, self.column)
430  }
431
432  pub fn peek_forward(&self) -> char {
433    *self.peek_forward_many::<1>().first().unwrap()
434  }
435
436  pub fn peek_forward_many<const AMOUNT: usize>(&self) -> [char; AMOUNT] {
437    self
438      .inner
439      .peek_forward_many::<AMOUNT>()
440      .iter()
441      .map(|x| x.unwrap_or('\0'))
442      .collect::<Vec<_>>()
443      .try_into()
444      .unwrap()
445  }
446
447  pub fn peek_backward(&self) -> char {
448    *self.peek_backward_many::<1>().first().unwrap()
449  }
450
451  pub fn peek_backward_many<const AMOUNT: usize>(&self) -> [char; AMOUNT] {
452    self
453      .inner
454      .peek_backward_many::<AMOUNT>()
455      .iter()
456      .map(|x| x.unwrap_or('\0'))
457      .collect::<Vec<_>>()
458      .try_into()
459      .unwrap()
460  }
461
462  pub fn consume(&mut self) -> char {
463    *self.consume_many::<1, 0>().first().unwrap()
464  }
465
466  pub fn consume_if<F>(&mut self, predicate: F) -> char
467  where
468    F: FnOnce(char) -> bool,
469  {
470    *self
471      .consume_many_if::<_, 1, 0>(|v| {
472        let x = *v.first().unwrap();
473        predicate(x)
474      })
475      .first()
476      .unwrap()
477  }
478
479  pub fn consume_many<const AMOUNT: usize, const L: isize>(
480    &mut self,
481  ) -> [char; AMOUNT + L.unsigned_abs()] {
482    self
483      .inner
484      .consume_many::<AMOUNT, L>()
485      .iter()
486      .filter_map(|x| {
487        if let Some(x) = x {
488          self.column_queue.push(self.column);
489          if *x == '\n' {
490            self.line_queue.push(self.line);
491            self.line += 1;
492            self.column = 0;
493          } else {
494            self.column += 1;
495          }
496          self.line_queue.truncate(16);
497          self.column_queue.truncate(16);
498        }
499        x.or(Some('\0'))
500      })
501      .collect::<Vec<_>>()
502      .try_into()
503      .unwrap()
504  }
505
506  pub fn consume_many_if<F, const AMOUNT: usize, const L: isize>(
507    &mut self,
508    predicate: F,
509  ) -> [char; AMOUNT + L.unsigned_abs()]
510  where
511    F: FnOnce(Vec<char>) -> bool,
512  {
513    let l = self
514      .inner
515      .look_around::<AMOUNT, L, true>()
516      .iter()
517      .map(|x| x.unwrap_or('\0'))
518      .collect::<Vec<_>>()
519      .into_boxed_slice();
520    if predicate(l.to_vec()) {
521      self.consume_many::<AMOUNT, L>()
522    } else {
523      ['\0'; AMOUNT + L.unsigned_abs()]
524    }
525  }
526
527  pub fn restore(&mut self) -> char {
528    *self.restore_many::<1, 0>().first().unwrap()
529  }
530
531  pub fn restore_if<F>(&mut self, predicate: F) -> char
532  where
533    F: FnOnce(char) -> bool,
534  {
535    *self
536      .restore_many_if::<_, 1, 0>(|v| {
537        let x = *v.first().unwrap();
538        predicate(x)
539      })
540      .first()
541      .unwrap()
542  }
543
544  pub fn restore_many<const AMOUNT: usize, const L: isize>(
545    &mut self,
546  ) -> [char; AMOUNT + L.unsigned_abs()] {
547    self
548      .inner
549      .restore_many::<AMOUNT, L>()
550      .iter()
551      .filter_map(|x| {
552        if let Some(x) = x {
553          self.column = self.column_queue.pop().unwrap_or(0);
554          if *x == '\n' {
555            self.line = self.line_queue.pop().unwrap_or(0);
556          }
557        }
558        x.or(Some('\0'))
559      })
560      .collect::<Vec<_>>()
561      .try_into()
562      .unwrap()
563  }
564
565  pub fn restore_many_if<F, const AMOUNT: usize, const L: isize>(
566    &mut self,
567    predicate: F,
568  ) -> [char; AMOUNT + L.unsigned_abs()]
569  where
570    F: FnOnce(Vec<char>) -> bool,
571  {
572    let l = self
573      .inner
574      .look_around::<AMOUNT, L, false>()
575      .iter()
576      .map(|x| x.unwrap_or('\0'))
577      .collect::<Vec<_>>()
578      .into_boxed_slice();
579    if predicate(l.to_vec()) {
580      self.restore_many::<AMOUNT, L>()
581    } else {
582      ['\0'; AMOUNT + L.unsigned_abs()]
583    }
584  }
585}
586
587#[cfg(test)]
588mod tests {
589  use super::{
590    IntoSlipperyCharsIterator, IntoSlipperyIterator, SlipperyCharsIter, SlipperyCharsIterator,
591    SlipperyIter, SlipperyIterator,
592  };
593  use std::ops::RangeInclusive;
594
595  #[test]
596  pub fn slippery_iter_construct_and_collect() {
597    let orig = 0..=10;
598    let orig_iter = orig.clone();
599
600    let s_iter_1: SlipperyIter<'_, RangeInclusive<i32>> = orig_iter.clone().into();
601    let s_iter_2 = orig_iter.clone().slippery();
602    let s_iter_3 = orig.into_slippery_iter();
603    let s_iter_4 = orig_iter.clone().into_slippery_iter();
604
605    assert_eq!(
606      s_iter_1.collect::<Vec<_>>(),
607      orig_iter.clone().collect::<Vec<_>>(),
608    );
609    assert_eq!(
610      s_iter_2.collect::<Vec<_>>(),
611      orig_iter.clone().collect::<Vec<_>>(),
612    );
613    assert_eq!(
614      s_iter_3.collect::<Vec<_>>(),
615      orig_iter.clone().collect::<Vec<_>>(),
616    );
617    assert_eq!(
618      s_iter_4.collect::<Vec<_>>(),
619      orig_iter.clone().collect::<Vec<_>>(),
620    );
621  }
622
623  #[test]
624  pub fn slippery_iter_peek_forward() {
625    let iter = (0..=10).slippery();
626
627    assert_eq!(iter.peek_forward(), Some(0));
628    assert_eq!(
629      iter.peek_forward_many::<7>().to_vec(),
630      [
631        Some(0),
632        Some(1),
633        Some(2),
634        Some(3),
635        Some(4),
636        Some(5),
637        Some(6)
638      ]
639      .to_vec(),
640    );
641  }
642
643  #[test]
644  pub fn slippery_iter_peek_backward() {
645    let mut iter = (0..=10).slippery();
646    iter.consume_many::<6, 0>();
647
648    assert_eq!(iter.peek_backward(), Some(5));
649    assert_eq!(
650      iter.peek_backward_many::<6>().to_vec(),
651      [Some(5), Some(4), Some(3), Some(2), Some(1), Some(0),].to_vec(),
652    );
653  }
654
655  #[test]
656  pub fn slippery_iter_consume() {
657    let mut iter = (0..=10).slippery();
658
659    assert_eq!(iter.consume(), Some(0));
660    assert_eq!(iter.peek_forward(), Some(1));
661    assert_eq!(
662      iter.consume_many::<5, 1>().to_vec(),
663      [Some(1), Some(2), Some(3), Some(4), Some(5), Some(6),].to_vec(),
664    );
665    assert_eq!(iter.peek_forward(), Some(6));
666  }
667
668  #[test]
669  pub fn slippery_iter_restore() {
670    let mut iter = (0..=10).slippery();
671
672    assert_eq!(
673      iter.consume_many::<11, 0>().to_vec(),
674      [
675        Some(0),
676        Some(1),
677        Some(2),
678        Some(3),
679        Some(4),
680        Some(5),
681        Some(6),
682        Some(7),
683        Some(8),
684        Some(9),
685        Some(10),
686      ]
687      .to_vec()
688    );
689    assert_eq!(iter.peek_forward(), None);
690    assert_eq!(iter.peek_backward(), Some(10));
691    assert_eq!(iter.restore(), Some(10));
692    assert_eq!(iter.peek_backward(), Some(9));
693    assert_eq!(
694      iter.restore_many::<5, -1>().to_vec(),
695      [Some(9), Some(8), Some(7), Some(6), Some(5), Some(4),].to_vec()
696    );
697  }
698
699  #[test]
700  #[allow(noop_method_call)]
701  pub fn slippery_chars_iter_construct_and_collect() {
702    let orig = "abcdefghijklmnopqrstuvwxyz";
703    let orig_iter = orig.clone().chars();
704
705    let s_iter_1: SlipperyCharsIter<'_> = orig_iter.clone().into();
706    let s_iter_2 = orig.clone().slippery_chars();
707    let s_iter_3 = orig_iter.clone().into_slippery_chars_iter();
708
709    assert_eq!(
710      s_iter_1.collect::<Vec<_>>(),
711      orig_iter.clone().collect::<Vec<_>>()
712    );
713    assert_eq!(
714      s_iter_2.collect::<Vec<_>>(),
715      orig_iter.clone().collect::<Vec<_>>()
716    );
717    assert_eq!(
718      s_iter_3.collect::<Vec<_>>(),
719      orig_iter.clone().collect::<Vec<_>>()
720    );
721  }
722
723  #[test]
724  pub fn slippery_chars_iter_peek_forward() {
725    let iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
726
727    assert_eq!(iter.peek_forward(), 'a');
728    assert_eq!(
729      iter.peek_forward_many::<6>().to_vec(),
730      ['a', 'b', 'c', 'd', 'e', 'f',].to_vec()
731    );
732  }
733
734  #[test]
735  pub fn slippery_chars_iter_peek_backward() {
736    let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
737    iter.consume_many::<6, 0>();
738
739    assert_eq!(iter.peek_backward(), 'f');
740    assert_eq!(
741      iter.peek_backward_many::<6>().to_vec(),
742      ['f', 'e', 'd', 'c', 'b', 'a',].to_vec()
743    );
744  }
745
746  #[test]
747  pub fn slippery_chars_iter_consume() {
748    let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
749
750    assert_eq!(iter.consume(), 'a');
751    assert_eq!(iter.peek_forward(), 'b');
752    assert_eq!(
753      iter.consume_many::<5, 1>().to_vec(),
754      ['b', 'c', 'd', 'e', 'f', 'g',].to_vec()
755    );
756    assert_eq!(iter.peek_forward(), 'g');
757  }
758
759  #[test]
760  pub fn slippery_chars_iter_restore() {
761    let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
762
763    assert_eq!(
764      iter.consume_many::<26, 0>().to_vec(),
765      [
766        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
767        's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
768      ]
769      .to_vec()
770    );
771    assert_eq!(iter.peek_forward(), '\0');
772    assert_eq!(iter.peek_backward(), 'z');
773    assert_eq!(iter.restore(), 'z');
774    assert_eq!(iter.peek_backward(), 'y');
775    assert_eq!(
776      iter.restore_many::<5, -1>(),
777      ['y', 'x', 'w', 'v', 'u', 't',]
778    );
779  }
780}