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