add_ed/buffer/
iters.rs

1//! A module for an obfuscating iterator, to not leak too much implementation
2//! through the API.
3
4use crate::Line;
5
6// Type shorthand for the current implementation specific iterator, to reduce
7// how many times I have to write out this monstrosity of a type
8type Inner<'b> = std::iter::Map<
9  std::slice::Iter<'b, Line>, for<'a> fn(&'a Line) -> &'a str
10>;
11type TaggedInner<'b> = std::iter::Map<
12  std::slice::Iter<'b, Line>, for<'a> fn(&'a Line) -> (char, &'a str)
13>;
14
15/// The iterator returned by [`Ed::get_selection`]
16///
17/// To simplify [`IO`] testing it implements
18/// From<Box<dyn Iterator<Item = &str>>> when the "testing" feature is enabled.
19pub struct LinesIter<'a> {
20  // enum internal, so we can have a low cost match during testing and no
21  // overhead or generics complexity at runtime.
22  inner: LinesIterInner<'a>,
23}
24// Wrapped by struct, so we can hide the internal state
25enum LinesIterInner<'a> {
26  Real(Inner<'a>),
27  #[cfg(any(fuzzing, test))]
28  Test(Box<dyn Iterator<Item = &'a str>>),
29}
30
31impl<'a> Iterator for LinesIter<'a> {
32  type Item = &'a str;
33
34  fn next(&mut self) -> Option<Self::Item> {
35    match &mut self.inner {
36      LinesIterInner::Real(x) => x.next(),
37      #[cfg(any(fuzzing, test))]
38      LinesIterInner::Test(x) => x.next(),
39    }
40  }
41}
42
43impl<'a> From<Inner<'a>> for LinesIter<'a> {
44  fn from(i: Inner<'a>) -> Self {
45    Self{ inner: LinesIterInner::Real(i) }
46  }
47}
48
49#[cfg(any(fuzzing, test))]
50impl<'a, I: Iterator<Item=&'a str> + 'static> From<Box<I>> for LinesIter<'a> {
51  fn from(i: Box<I>) -> Self {
52    Self{ inner: LinesIterInner::Test(i) }
53  }
54}
55/// The iterator returned by [`Ed::get_tagged_selection`]
56///
57/// As it isn't specifically required by anything there is no testing
58/// functionality added.
59pub struct TaggedLinesIter<'a> {
60  inner: TaggedInner<'a>,
61}
62
63impl<'a> Iterator for TaggedLinesIter<'a> {
64  type Item = (char, &'a str);
65
66  fn next(&mut self) -> Option<Self::Item> {
67    self.inner.next()
68  }
69}
70
71impl<'a> From<TaggedInner<'a>> for TaggedLinesIter<'a> {
72  fn from(i: TaggedInner<'a>) -> Self {
73    Self{ inner: i }
74  }
75}