1use core::{cmp, fmt};
2use std::cell::RefCell;
3use std::io::{Cursor, Read, Result, Seek, SeekFrom};
4
5use crate::file::reader::{Length, TryClone};
6
7const DEFAULT_BUF_SIZE: usize = 8 * 1024;
8
9pub trait TsFileReader: Read + Seek + Length + TryClone {}
10
11impl<T: Read + Seek + Length + TryClone> TsFileReader for T {}
12
13pub struct FileSource<R: TsFileReader> {
14 reader: RefCell<R>,
15 start: u64,
16 end: u64,
17 buf: Vec<u8>,
18 buf_pos: usize,
19 buf_cap: usize,
20}
21
22pub trait Position {
23 fn pos(&self) -> u64;
25}
26
27impl<R: TsFileReader> fmt::Debug for FileSource<R> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.debug_struct("FileSource")
30 .field("reader", &"OPAQUE")
31 .field("start", &self.start)
32 .field("end", &self.end)
33 .field("buf.len", &self.buf.len())
34 .field("buf_pos", &self.buf_pos)
35 .field("buf_cap", &self.buf_cap)
36 .finish()
37 }
38}
39
40impl<R: TsFileReader> FileSource<R> {
41 pub fn new(fd: &R, start: u64, length: usize) -> Self {
42 let reader = RefCell::new(fd.try_clone().unwrap());
43 Self {
44 reader,
45 start,
46 end: start + length as u64,
47 buf: vec![0_u8; DEFAULT_BUF_SIZE],
48 buf_pos: 0,
49 buf_cap: 0,
50 }
51 }
52
53 fn fill_inner_buf(&mut self) -> Result<&[u8]> {
54 if self.buf_pos >= self.buf_cap {
55 debug_assert!(self.buf_pos == self.buf_cap);
60 let mut reader = self.reader.borrow_mut();
61 reader.seek(SeekFrom::Start(self.start))?; self.buf_cap = reader.read(&mut self.buf)?;
63 self.buf_pos = 0;
64 }
65 Ok(&self.buf[self.buf_pos..self.buf_cap])
66 }
67
68 fn skip_inner_buf(&mut self, buf: &mut [u8]) -> Result<usize> {
69 self.buf_pos = 0;
71 self.buf_cap = 0;
72 let mut reader = self.reader.borrow_mut();
74 reader.seek(SeekFrom::Start(self.start))?; let nread = reader.read(buf)?;
76 self.start += nread as u64;
77 Ok(nread)
78 }
79}
80
81impl<R: TsFileReader> Read for FileSource<R> {
82 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
83 let bytes_to_read = cmp::min(buf.len(), (self.end - self.start) as usize);
84 let buf = &mut buf[0..bytes_to_read];
85
86 if self.buf_pos == self.buf_cap && buf.len() >= self.buf.len() {
90 return self.skip_inner_buf(buf);
91 }
92 let nread = {
93 let mut rem = self.fill_inner_buf()?;
94 rem.read(buf)?
96 };
97 self.buf_pos = cmp::min(self.buf_pos + nread, self.buf_cap);
99
100 self.start += nread as u64;
101 Ok(nread)
102 }
103}
104
105impl<R: TsFileReader> Position for FileSource<R> {
106 fn pos(&self) -> u64 {
107 self.start
108 }
109}
110
111impl<R: TsFileReader> Length for FileSource<R> {
112 fn len(&self) -> u64 {
113 self.end - self.start
114 }
115}