over/parse/
char_stream.rs1use std::cell::RefCell;
4use std::fs::File;
5use std::io;
6use std::io::Read;
7use std::iter::Peekable;
8use std::mem;
9use std::rc::Rc;
10use std::str::Chars;
11
12#[derive(Clone, Debug)]
13struct Inner {
14 file: Option<String>,
15 contents: String,
16 stream: Peekable<Chars<'static>>,
17 line: usize,
18 col: usize,
19}
20
21#[derive(Clone, Debug)]
22pub struct CharStream {
23 inner: Rc<RefCell<Inner>>,
24}
25
26impl CharStream {
27 pub fn from_file(path: &str) -> io::Result<CharStream> {
28 let mut file = File::open(path)?;
29
30 let len = file.metadata()?.len();
31 let mut contents = String::with_capacity(len as usize);
32
33 file.read_to_string(&mut contents)?;
34
35 Self::from_string_impl(Some(String::from(path)), contents)
36 }
37
38 pub fn from_string(contents: String) -> io::Result<CharStream> {
39 Self::from_string_impl(None, contents)
40 }
41
42 fn from_string_impl(file: Option<String>, contents: String) -> io::Result<CharStream> {
43 let chars: Chars = unsafe { mem::transmute(contents.chars()) };
44 let stream = chars.peekable();
45
46 Ok(CharStream {
47 inner: Rc::new(RefCell::new(Inner {
48 file,
49 contents,
50 stream,
51 line: 1,
52 col: 1,
53 })),
54 })
55 }
56
57 pub fn peek(&self) -> Option<char> {
58 let mut inner = self.inner.borrow_mut();
59 let opt = inner.stream.peek();
60
61 match opt {
62 Some(ch) => Some(*ch),
63 None => None,
64 }
65 }
66
67 pub fn file(&self) -> Option<String> {
68 let inner = self.inner.borrow();
69 inner.file.clone()
70 }
71
72 pub fn line(&self) -> usize {
73 let inner = self.inner.borrow();
74 inner.line
75 }
76
77 pub fn col(&self) -> usize {
78 let inner = self.inner.borrow();
79 inner.col
80 }
81
82 fn set_line(&mut self, value: usize) {
83 let mut inner = self.inner.borrow_mut();
84 inner.line = value;
85 }
86
87 fn set_col(&mut self, value: usize) {
88 let mut inner = self.inner.borrow_mut();
89 inner.col = value;
90 }
91}
92
93impl Iterator for CharStream {
94 type Item = char;
95
96 fn next(&mut self) -> Option<Self::Item> {
97 let opt = {
98 let mut inner = self.inner.borrow_mut();
99 inner.stream.next()
100 };
101
102 match opt {
103 Some(ch) => {
104 if ch == '\n' {
105 let line = self.line();
106 self.set_line(line + 1);
107 self.set_col(1);
108 } else {
109 let col = self.col();
110 self.set_col(col + 1);
111 }
112 Some(ch)
113 }
114 None => None,
115 }
116 }
117}