abortable_parser/
iter.rs

1// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
2//
3//  Licensed under the Apache License, Version 2.0 (the "License");
4//  you may not use this file except in compliance with the License.
5//  You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14
15//! Contains implementations of `InputIter`.
16use std::fmt::Debug;
17use std::iter::Iterator;
18
19use super::{InputIter, Offsetable, Positioned, Seekable, Span, SpanRange};
20
21/// Implements `InputIter` for any slice of T.
22#[derive(Debug)]
23pub struct SliceIter<'a, T: Debug + 'a> {
24    source: &'a [T],
25    offset: usize,
26}
27
28impl<'a, T: Debug + 'a> SliceIter<'a, T> {
29    /// new constructs a SliceIter from a Slice of T.
30    pub fn new(source: &'a [T]) -> Self {
31        SliceIter {
32            source: source,
33            offset: 0,
34        }
35    }
36}
37
38impl<'a, T: Debug + 'a> Iterator for SliceIter<'a, T> {
39    type Item = &'a T;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        match self.source.get(self.offset) {
43            Some(item) => {
44                self.offset += 1;
45                Some(item)
46            }
47            None => None,
48        }
49    }
50}
51
52impl<'a, T: Debug + 'a> Offsetable for SliceIter<'a, T> {
53    fn get_offset(&self) -> usize {
54        self.offset
55    }
56}
57
58impl<'a, It> Positioned for SliceIter<'a, It>
59where
60    It: Positioned + Debug,
61{
62    fn line(&self) -> usize {
63        match self.peek_next() {
64            Some(i) => i.line(),
65            None => 0,
66        }
67    }
68
69    fn column(&self) -> usize {
70        match self.peek_next() {
71            Some(i) => i.column(),
72            None => 0,
73        }
74    }
75}
76
77impl<'a, T: Debug + 'a> Clone for SliceIter<'a, T> {
78    fn clone(&self) -> Self {
79        SliceIter {
80            source: self.source,
81            offset: self.offset,
82        }
83    }
84}
85
86impl<'a, T: Debug + 'a> InputIter for SliceIter<'a, T> {
87    fn curr(&self) -> Self::Item {
88        if self.offset >= self.source.len() {
89            self.source.get(self.source.len() - 1).unwrap()
90        } else {
91            if self.offset == 0 {
92                self.source.get(self.offset).unwrap()
93            } else {
94                self.source.get(self.offset - 1).unwrap()
95            }
96        }
97    }
98}
99
100impl<'a, T: Debug + 'a> Span<&'a [T]> for SliceIter<'a, T> {
101    fn span(&self, idx: SpanRange) -> &'a [T] {
102        match idx {
103            SpanRange::Range(r) => self.source.index(r),
104            SpanRange::RangeTo(r) => self.source.index(r),
105            SpanRange::RangeFrom(r) => self.source.index(r),
106            SpanRange::RangeFull(r) => self.source.index(r),
107        }
108    }
109}
110
111impl<'a> From<&'a str> for SliceIter<'a, u8> {
112    fn from(source: &'a str) -> Self {
113        SliceIter::new(source.as_bytes())
114    }
115}
116
117impl<'a, T: Debug> From<&'a [T]> for SliceIter<'a, T> {
118    fn from(source: &'a [T]) -> Self {
119        SliceIter::new(source)
120    }
121}
122
123impl<'a, T: Debug> From<&'a Vec<T>> for SliceIter<'a, T> {
124    fn from(source: &'a Vec<T>) -> Self {
125        SliceIter::new(source.as_slice())
126    }
127}
128
129impl<'a, O: Debug> Peekable<&'a O> for SliceIter<'a, O> {
130    fn peek_next(&self) -> Option<&'a O> {
131        self.source.get(self.offset)
132    }
133}
134
135/// Implements `InputIter` for any slice of T.
136#[derive(Debug)]
137pub struct StrIter<'a> {
138    source: &'a str,
139    offset: usize,
140    line: usize,
141    column: usize,
142}
143
144impl<'a> StrIter<'a> {
145    /// new constructs a StrIter from a Slice of T.
146    pub fn new(source: &'a str) -> Self {
147        StrIter {
148            source: source,
149            offset: 0,
150            line: 1,
151            column: 1,
152        }
153    }
154}
155
156impl<'a> Iterator for StrIter<'a> {
157    type Item = &'a u8;
158
159    fn next(&mut self) -> Option<Self::Item> {
160        match self.source.as_bytes().get(self.offset) {
161            // TODO count lines and columns.
162            Some(item) => {
163                self.offset += 1;
164                if *item == b'\n' {
165                    self.line += 1;
166                    self.column = 1;
167                } else {
168                    self.column += 1;
169                }
170                Some(item)
171            }
172            None => None,
173        }
174    }
175}
176
177impl<'a> Offsetable for StrIter<'a> {
178    fn get_offset(&self) -> usize {
179        self.offset
180    }
181}
182
183impl<'a> Positioned for StrIter<'a> {
184    fn line(&self) -> usize {
185        self.line
186    }
187
188    fn column(&self) -> usize {
189        self.column
190    }
191}
192
193impl<'a> Clone for StrIter<'a> {
194    fn clone(&self) -> Self {
195        StrIter {
196            source: self.source,
197            offset: self.offset,
198            line: self.line,
199            column: self.column,
200        }
201    }
202}
203
204impl<'a> InputIter for StrIter<'a> {
205    fn curr(&self) -> Self::Item {
206        if self.offset >= self.source.len() {
207            self.source.as_bytes().get(self.source.len() - 1).unwrap()
208        } else {
209            if self.offset == 0 {
210                self.source.as_bytes().get(self.offset).unwrap()
211            } else {
212                self.source.as_bytes().get(self.offset - 1).unwrap()
213            }
214        }
215    }
216}
217
218impl<'a> From<&'a str> for StrIter<'a> {
219    fn from(source: &'a str) -> Self {
220        Self::new(source)
221    }
222}
223
224use std::ops::Index;
225
226impl<'a> Span<&'a str> for StrIter<'a> {
227    fn span(&self, idx: SpanRange) -> &'a str {
228        match idx {
229            SpanRange::Range(r) => self.source.index(r),
230            SpanRange::RangeTo(r) => self.source.index(r),
231            SpanRange::RangeFrom(r) => self.source.index(r),
232            SpanRange::RangeFull(r) => self.source.index(r),
233        }
234    }
235}
236
237impl<'a> Seekable for StrIter<'a> {
238    fn seek(&mut self, to: usize) -> usize {
239        let self_len = self.source.len();
240        let offset = if self_len > to { to } else { self_len };
241        self.offset = offset;
242        self.offset
243    }
244}
245
246use super::Peekable;
247
248impl<'a> Peekable<&'a u8> for StrIter<'a> {
249    fn peek_next(&self) -> Option<&'a u8> {
250        self.source.as_bytes().get(self.offset)
251    }
252}