ucglib/
iter.rs

1//! Input stream wrappers for use in abortable_parser.
2use std::convert::From;
3use std::iter::Iterator;
4use std::path::PathBuf;
5
6use abortable_parser::iter::{SliceIter, StrIter};
7use abortable_parser::{InputIter, Offsetable, Peekable, Positioned, Seekable, Span, SpanRange};
8
9use crate::ast::{Position, Token};
10
11#[derive(Debug)]
12pub struct OffsetStrIter<'a> {
13    source_file: Option<PathBuf>,
14    contained: StrIter<'a>,
15    line_offset: usize,
16    col_offset: usize,
17}
18
19impl<'a> OffsetStrIter<'a> {
20    pub fn new(input: &'a str) -> Self {
21        Self::new_with_offsets(input, 0, 0)
22    }
23
24    pub fn new_with_offsets(input: &'a str, line_offset: usize, col_offset: usize) -> Self {
25        OffsetStrIter {
26            source_file: None,
27            contained: StrIter::new(input),
28            line_offset: line_offset,
29            col_offset: col_offset,
30        }
31    }
32
33    pub fn with_src_file<P: Into<PathBuf>>(mut self, file: P) -> Self {
34        self.source_file = Some(file.into());
35        self
36    }
37}
38
39impl<'a> Iterator for OffsetStrIter<'a> {
40    type Item = &'a u8;
41
42    fn next(&mut self) -> Option<Self::Item> {
43        self.contained.next()
44    }
45}
46
47impl<'a> Offsetable for OffsetStrIter<'a> {
48    fn get_offset(&self) -> usize {
49        self.contained.get_offset()
50    }
51}
52
53impl<'a> Clone for OffsetStrIter<'a> {
54    fn clone(&self) -> Self {
55        OffsetStrIter {
56            source_file: self.source_file.clone(),
57            contained: self.contained.clone(),
58            line_offset: self.line_offset,
59            col_offset: self.col_offset,
60        }
61    }
62}
63
64impl<'a> From<&'a str> for OffsetStrIter<'a> {
65    fn from(source: &'a str) -> Self {
66        OffsetStrIter {
67            source_file: None,
68            contained: StrIter::new(source),
69            line_offset: 0,
70            col_offset: 0,
71        }
72    }
73}
74
75impl<'a> Seekable for OffsetStrIter<'a> {
76    fn seek(&mut self, to: usize) -> usize {
77        self.contained.seek(to)
78    }
79}
80
81impl<'a> Span<&'a str> for OffsetStrIter<'a> {
82    fn span(&self, idx: SpanRange) -> &'a str {
83        self.contained.span(idx)
84    }
85}
86
87impl<'a> Peekable<&'a u8> for OffsetStrIter<'a> {
88    fn peek_next(&self) -> Option<&'a u8> {
89        self.contained.peek_next()
90    }
91}
92
93impl<'a> Positioned for OffsetStrIter<'a> {
94    fn line(&self) -> usize {
95        self.contained.line() + self.line_offset
96    }
97
98    fn column(&self) -> usize {
99        self.contained.column() + self.col_offset
100    }
101}
102
103impl<'a> InputIter for OffsetStrIter<'a> {
104    fn curr(&self) -> Self::Item {
105        self.clone().peek_next().unwrap()
106    }
107}
108
109impl<'a> From<&'a SliceIter<'a, Token>> for Position {
110    fn from(source: &'a SliceIter<'a, Token>) -> Self {
111        match source.peek_next() {
112            Some(t) => t.pos.clone(),
113            None => source.curr().pos.clone(),
114        }
115    }
116}
117
118impl<'a> From<&'a OffsetStrIter<'a>> for Position {
119    fn from(s: &'a OffsetStrIter<'a>) -> Position {
120        Position {
121            file: s.source_file.clone(),
122            line: s.line(),
123            column: s.column(),
124            offset: s.get_offset(),
125        }
126    }
127}
128
129pub trait FilePositioned: Positioned {
130    fn file(&self) -> Option<&PathBuf>;
131}
132
133impl<'a> FilePositioned for OffsetStrIter<'a> {
134    fn file(&self) -> Option<&PathBuf> {
135        self.source_file.as_ref()
136    }
137}
138
139impl<'a> FilePositioned for SliceIter<'a, Token> {
140    fn file(&self) -> Option<&PathBuf> {
141        match self.peek_next() {
142            Some(t) => t.pos.file.as_ref(),
143            None => None,
144        }
145    }
146}