pear/input/text_file.rs
1// use std::fs::File;
2// use std::io::{self, Read, BufReader};
3
4// use std::cmp::min;
5// use std::marker::PhantomData;
6
7// // Ideally, this would hold a `String` inside. But we need a lifetime parameter
8// // here so we can return an &'a str from `peek_slice`. The alternative is to
9// // give a lifetime to the `Input` trait and use it in the `peek_slice` method.
10// // But that lifetime will pollute everything. Finally, the _correct_ thing is
11// // for Rust to let us reference the lifetime of `self` in an associated type.
12// // That requires something like https://github.com/rust-lang/rfcs/pull/1598.
13// #[derive(Debug)]
14// pub struct StringFile<'s> {
15// buffer: Vec<u8>,
16// consumed: usize,
17// pos: usize,
18// reader: BufReader<File>,
19// _string: PhantomData<&'s str>
20// }
21
22// impl<'s> StringFile<'s> {
23// #[inline(always)]
24// pub fn open(path: &str) -> io::Result<StringFile<'s>> {
25// Ok(StringFile::new(File::open(path)?, 1024))
26// }
27
28// #[inline(always)]
29// pub fn open_with_cap(path: &str, cap: usize) -> io::Result<StringFile<'s>> {
30// Ok(StringFile::new(File::open(path)?, cap))
31// }
32
33// #[inline(always)]
34// pub fn new(file: File, cap: usize) -> StringFile<'s> {
35// StringFile {
36// buffer: vec![0; cap],
37// consumed: 0,
38// pos: 0,
39// reader: BufReader::new(file),
40// _string: PhantomData
41// }
42// }
43
44// #[inline(always)]
45// pub fn available(&self) -> usize {
46// self.pos - self.consumed
47// }
48
49// fn read_into_peek(&mut self, num: usize) -> io::Result<usize> {
50// if self.available() >= num {
51// return Ok(num);
52// }
53
54// let needed = num - self.available();
55// let to_read = min(self.buffer.len() - self.pos, needed);
56// let (i, j) = (self.pos, self.pos + to_read);
57// let read = self.reader.read(&mut self.buffer[i..j])?;
58
59// self.pos += read;
60// Ok(self.available())
61// }
62
63// // Panics if at least `num` aren't available.
64// #[inline(always)]
65// fn peek_bytes(&self, num: usize) -> &[u8] {
66// &self.buffer[self.consumed..(self.consumed + num)]
67// }
68
69// fn consume(&mut self, num: usize) {
70// if self.pos < num {
71// let left = (num - self.pos) as u64;
72// self.consumed = 0;
73// self.pos = 0;
74// // TOOD: Probably don't ignore this?
75// let _ = io::copy(&mut self.reader.by_ref().take(left), &mut io::sink());
76// } else {
77// self.consumed += num;
78// }
79// }
80
81// #[inline]
82// fn peek_char(&mut self) -> Option<char> {
83// let available = match self.read_into_peek(4) {
84// Ok(n) => n,
85// Err(_) => return None
86// };
87
88// let bytes = self.peek_bytes(available);
89// let string = match ::std::str::from_utf8(bytes) {
90// Ok(string) => string,
91// Err(e) => match ::std::str::from_utf8(&bytes[..e.valid_up_to()]) {
92// Ok(string) => string,
93// Err(_) => return None
94// }
95// };
96
97// string.chars().next()
98// }
99// }
100
101// impl<'s> Input for StringFile<'s> {
102// type Token = char;
103// type InSlice = &'s str;
104// type Slice = &'s str;
105// type Many = String;
106// type Context = &'s str;
107
108// // If we took Self::Token here, we'd know the length of the character.
109// #[inline(always)]
110// fn peek(&mut self) -> Option<Self::Token> {
111// self.peek_char()
112// }
113
114// fn take_many<F: FnMut(&Self::Token) -> bool>(&mut self, mut cond: F) -> Self::Many {
115// let mut result = String::new();
116// while let Some(c) = self.peek_char() {
117// if cond(&c) {
118// result.push(c);
119// self.consume(c.len_utf8());
120// } else {
121// break;
122// }
123// }
124
125// result
126// }
127
128// fn skip_many<F: FnMut(&Self::Token) -> bool>(&mut self, mut cond: F) -> usize {
129// let mut taken = 0;
130// while let Some(c) = self.peek_char() {
131// if cond(&c) {
132// self.consume(c.len_utf8());
133// taken += 1;
134// } else {
135// return taken;
136// }
137// }
138
139// taken
140// }
141
142// fn peek_slice(&mut self, slice: Self::InSlice) -> Option<Self::Slice> {
143// let available = match self.read_into_peek(slice.len()) {
144// Ok(n) => n,
145// Err(_) => return None
146// };
147
148// let bytes = self.peek_bytes(available);
149// let string = match ::std::str::from_utf8(bytes) {
150// Ok(string) => string,
151// Err(e) => match ::std::str::from_utf8(&bytes[..e.valid_up_to()]) {
152// Ok(string) => string,
153// Err(_) => return None
154// }
155// };
156
157// match string == slice {
158// true => Some(slice),
159// false => None
160// }
161// }
162
163// #[inline(always)]
164// fn advance(&mut self, count: usize) {
165// self.consume(count);
166// }
167
168// #[inline(always)]
169// fn is_empty(&mut self) -> bool {
170// match self.read_into_peek(1) {
171// Ok(0) | Err(_) => true,
172// Ok(_) => false,
173// }
174// }
175// }
176