reading_liner/stream/
stream.rs1use crate::{
2 location::{Offset, line_column},
3 stream::alias::{Guard, IndexRef, MutGuard},
4};
5use std::io;
6
7#[derive(Debug)]
22pub struct Stream<'index, Reader> {
23 reader: Reader,
24 index: IndexRef<'index>,
25
26 next_offset: Offset,
27 current_line: usize,
28 base: usize, }
30
31impl<'index, R> Stream<'index, R> {
32 pub fn new(reader: R, index: IndexRef<'index>) -> Self {
33 Self {
34 reader,
35 base: 0,
36 index,
37 next_offset: 0.into(),
38 current_line: 0,
39 }
40 }
41
42 pub fn get_ref(&self) -> &R {
43 &self.reader
44 }
45
46 #[inline]
47 pub fn base(&self) -> usize {
48 self.base
49 }
50
51 #[inline]
52 pub fn get_index(&self) -> Guard<'_> {
53 self.index.get()
54 }
55
56 #[inline]
57 pub fn get_index_mut(&mut self) -> MutGuard<'_> {
58 self.index.get_mut()
59 }
60}
61
62impl<'index, R: io::Read> Stream<'index, R> {
63 #[inline]
65 pub fn read_len(&self) -> usize {
66 self.next_offset.raw()
67 }
68
69 fn forward(&mut self, buf: &mut [u8]) -> io::Result<usize> {
71 let n = self.reader.read(buf)?;
72
73 for (offset, b) in buf.iter().take(n).enumerate() {
74 if *b == b'\n' {
75 self.current_line += 1;
76 let next_offset = self.next_offset;
77 self.get_index_mut().add_next_line(next_offset + offset + 1); continue;
80 }
81 }
82
83 if !buf.is_empty() && n == 0 {
85 let end = self.get_index().end();
87 let next_offset = self.next_offset;
88
89 match end {
90 Some(end) if end != next_offset => {
91 self.get_index_mut().add_next_line(next_offset);
92 }
93 None => self.get_index_mut().add_next_line(next_offset),
94 _ => {}
95 }
96 }
97
98 self.next_offset += n;
99 Ok(n)
100 }
101
102 pub fn locate(&mut self, offset: Offset, buf: &mut [u8]) -> io::Result<line_column::ZeroBased> {
125 let line = self.locate_line(offset, buf)?;
126 let line_offset = self.get_index().query().line_offset(line).unwrap();
127 let col = offset - line_offset;
128 Ok((line, col.raw()).into())
129 }
130
131 pub fn locate_line(&mut self, offset: Offset, buf: &mut [u8]) -> io::Result<usize> {
144 let mut begin = 0;
145 loop {
146 if let Some(i) = self
150 .get_index()
151 .query()
152 .range_from(begin..)
153 .locate_line(offset)
154 {
155 break Ok(i); }
157 begin = self.get_index().count();
158
159 if self.forward(buf)? == 0 {
160 break Err(io_error("Invalid offset, exceed EOF"));
161 }
162 }
163 }
164
165 pub fn encode(
184 &mut self,
185 line_index: line_column::ZeroBased,
186 buf: &mut [u8],
187 ) -> io::Result<Offset> {
188 let (line, col) = line_index.raw();
189 loop {
190 if let Some(offset) = self.get_index().query().line_offset(line) {
191 break Ok(offset + col);
192 }
193
194 if self.forward(buf)? == 0 {
195 break Err(io_error(format!("Invalid line index: ({}, {})", line, col)));
196 }
197 }
198 }
199
200 pub fn drain(&mut self, buf: &mut [u8]) -> io::Result<()> {
202 loop {
203 let n = self.forward(buf)?;
204 if n == 0 {
205 return Ok(());
206 }
207 }
208 }
209}
210
211impl<'index, R: io::Read> io::Read for Stream<'index, R> {
213 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
214 self.forward(buf)
215 }
216}
217
218#[inline]
219fn io_error<S: ToString>(msg: S) -> io::Error {
220 io::Error::new(io::ErrorKind::Other, msg.to_string())
221}
222
223#[cfg(test)]
224mod test {
225 #![allow(unused_must_use)]
226 use crate::Index;
227
228 use super::*;
229 use std::{
230 cell::RefCell,
231 io::{BufReader, Read},
232 rc::Rc,
233 };
234
235 static SRC: &'static str = "\nThis is s sim\nple test that\n I have to verify stream reader!";
236
237 #[test]
238 fn test_stream_str_buf() {
239 let mut index = Index::new();
240 let stream = Stream::new(SRC.as_bytes(), IndexRef::Direct(&mut index));
241 let mut reader = BufReader::new(stream);
242 let mut buf = String::new();
243 reader.read_to_string(&mut buf).unwrap();
244
245 let ans = reader.get_ref().get_index().query().locate(Offset(20));
246 assert!(ans.is_some());
247 assert_eq!(ans.unwrap(), (2, 5).into());
248 }
249
250 #[test]
251 fn test_stream_str_drain() {
252 let mut index = Index::new();
253 let mut stream = Stream::new(SRC.as_bytes(), IndexRef::Direct(&mut index));
254 let mut buf = vec![b'\0'; 10];
255 stream.drain(&mut buf);
256
257 let ans = stream.get_index().query().locate(Offset(20));
258 assert!(ans.is_some());
259 assert_eq!(ans.unwrap(), (2, 5).into());
260 }
261
262 #[test]
263 fn test_stream_str_incremental() {
264 let mut index = Index::new();
265 let mut stream = Stream::new(SRC.as_bytes(), IndexRef::Direct(&mut index));
266 let mut buf = vec![b'\0'; 10];
267
268 let ans = stream.locate(Offset(20), &mut buf);
269 assert!(ans.is_ok());
270 assert_eq!(ans.unwrap(), (2, 5).into());
271 }
272
273 #[test]
274 fn test_stream_str_incremental_rc() {
275 let index = Index::new();
276 let index = Rc::new(RefCell::new(index));
277
278 let mut stream = Stream::new(SRC.as_bytes(), IndexRef::Shared(index.clone()));
279 let mut buf = vec![b'\0'; 10];
280
281 let ans = stream.locate(Offset(20), &mut buf);
282 assert!(ans.is_ok());
283 assert_eq!(ans.unwrap(), (2, 5).into());
284
285 let ans = index.borrow().query().locate(Offset(20));
286 assert!(ans.is_some());
287 assert_eq!(ans.unwrap(), (2, 5).into());
288 }
289}