text_reader/
detector.rs

1use std::ffi::OsStr;
2
3use crate::TextReader;
4
5/// Text reader detector
6///
7/// # Examples
8///
9/// ```rust
10/// use text_reader::TextReader;
11/// use text_reader::Detector;
12///
13/// let text = r#""typeA""#;
14/// let mut reader = TextReader::new(text);
15/// let mut rets = Vec::new();
16/// while reader.has_next() {
17///   match reader.next() {
18///     Some('"') => {
19///       let mut detector = reader.detector();
20///       rets.push('"');
21///       if detector.next_text("type").yes() {
22///         detector.rollback();
23///         rets.push('t');
24///       }
25///       continue;
26///     }
27///     Some(ch) => {
28///       rets.push(ch);
29///       continue;
30///     }
31///     None => {}
32///   }
33/// }
34/// let ret = rets.iter().collect::<String>();
35/// println!("{}", ret); // "ttypeA"
36/// ```
37#[derive(Debug)]
38pub struct Detector<'a> {
39  reader: &'a mut TextReader,
40  compares: Vec<char>,
41  last_len: usize,
42}
43
44impl<'a> Detector<'a> {
45
46  /// Create detector
47  ///
48  /// # Examples
49  ///
50  /// ```rust
51  /// use text_reader::TextReader;
52  ///
53  /// let mut reader = TextReader::new("abc");
54  /// ```
55  pub fn new(reader: &'a mut TextReader) -> Self {
56    Self { reader, compares: Vec::new(), last_len: 0 }
57  }
58
59  /// Detect next char
60  ///
61  /// # Examples
62  ///
63  /// ```rust
64  /// use text_reader::TextReader;
65  ///
66  /// let mut reader = TextReader::new("abc");
67  /// let mut detector = reader.detector();
68  /// detector.next_char('a');
69  /// ```
70  pub fn next_char(&mut self, ch: char) -> &mut Self {
71    self.compares.push(ch);
72    self
73  }
74
75  /// Detect next string
76  ///
77  /// # Examples
78  ///
79  /// ```rust
80  /// use text_reader::TextReader;
81  ///
82  /// let mut reader = TextReader::new("abc");
83  /// let mut detector = reader.detector();
84  /// detector.next_text("ab");
85  /// ```
86  pub fn next_text<S: AsRef<OsStr>>(&mut self, text: S) -> &mut Self {
87    text.as_ref().to_str().unwrap().chars().collect::<Vec<char>>()
88      .iter()
89      .for_each(|ch| { self.next_char(ch.clone()); });
90    self
91  }
92
93  /// Detect result is true
94  ///
95  /// # Examples
96  ///
97  /// ```rust
98  /// use text_reader::TextReader;
99  ///
100  /// let mut vec = Vec::new();
101  /// let mut reader = TextReader::new("abc");
102  ///
103  /// while reader.has_next() {
104  ///   match reader.next() {
105  ///     Some(ch) => {
106  ///       let mut detector = reader.detector();
107  ///       if detector.next_text("bc").yes() {
108  ///         println!("Detect ab");
109  ///       }
110  ///       vec.push(ch);
111  ///     },
112  ///     None => {}
113  ///   }
114  /// }
115  /// println!("{}", vec.iter().collect::<String>()); // a
116  /// ```
117  pub fn yes(&mut self) -> bool {
118    self.detect()
119  }
120
121  /// Detect result is false
122  pub fn no(&mut self) -> bool {
123    !self.detect()
124  }
125
126  /// Rollback detector
127  /// If detect success detector not back position. if want, use rollback function to reset reader position
128  ///
129  /// # Examples
130  ///
131  /// ```rust
132  /// use text_reader::TextReader;
133  ///
134  /// let mut vec = Vec::new();
135  ///
136  /// let mut reader = TextReader::new("abc");
137  /// while reader.has_next() {
138  ///   match reader.next() {
139  ///     Some(ch) => {
140  ///       let mut detector = reader.detector();
141  ///       if detector.next_text("bc").yes() {
142  ///         detector.rollback();
143  ///         println!("Detect ab");
144  ///       }
145  ///       vec.push(ch);
146  ///     },
147  ///     None => {}
148  ///   }
149  /// }
150  /// println!("{}", vec.iter().collect::<String>()); // abc
151  /// ```
152  pub fn rollback(&mut self) -> &mut Self {
153    for _ in 0..self.last_len {
154      self.reader.back();
155    }
156    self
157  }
158
159  fn detect(&mut self) -> bool {
160    let mut ix = 0;
161    let len = self.compares.len();
162
163    while self.reader.has_next() {
164      match self.reader.next() {
165        Some(ch) => {
166          let compare = match self.compares.get(ix) {
167            Some(c) => c.clone(),
168            None => {
169              self.reader.back();
170              self.last_len = len;
171              return true;
172            }
173          };
174          if ch != compare {
175            self.restore(ix + 1);
176            return false;
177          }
178          ix += 1;
179        }
180        None => {
181          self.restore(ix);
182          return false;
183        }
184      }
185    }
186    let same = ix == len;
187    if !same {
188      self.restore(ix);
189    } else {
190      self.last_len = len;
191    }
192    same
193  }
194
195  fn restore(&mut self, count: usize) -> &mut Self {
196    if count == 0 {
197      return self;
198    }
199    for _ in 0..count {
200      self.reader.back();
201    }
202    self
203  }
204}
205