new streams
This commit is contained in:
parent
3963fc50c3
commit
c73be7166f
13 changed files with 748 additions and 174 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use std::{
|
||||
cell::RefCell,
|
||||
fs::File,
|
||||
io::{self, BufRead, BufReader},
|
||||
mem,
|
||||
|
|
@ -8,35 +9,36 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::tui::{
|
||||
filter::{Filter, FilterKind},
|
||||
model::{LogEntry, RawLogEntry},
|
||||
processing::LogStream,
|
||||
};
|
||||
|
||||
pub struct LogfileReader {
|
||||
struct Inner {
|
||||
pub path: PathBuf,
|
||||
file: BufReader<File>,
|
||||
|
||||
entries: Vec<Rc<LogEntry>>,
|
||||
filters: Vec<Rc<Filter>>,
|
||||
file: BufReader<File>,
|
||||
cached_entries: Vec<Rc<LogEntry>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LogfileReader(Rc<RefCell<Inner>>);
|
||||
|
||||
impl LogfileReader {
|
||||
pub fn new(p: &Path) -> io::Result<Self> {
|
||||
Ok(Self {
|
||||
Ok(Self(Rc::new(RefCell::new(Inner {
|
||||
file: BufReader::new(File::open(p)?),
|
||||
path: p.to_path_buf(),
|
||||
entries: Vec::new(),
|
||||
filters: Vec::new(),
|
||||
})
|
||||
cached_entries: Vec::new(),
|
||||
}))))
|
||||
}
|
||||
|
||||
pub fn add_filter(&mut self, filter: Filter) {
|
||||
self.filters.push(Rc::new(filter));
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0.borrow().path.clone()
|
||||
}
|
||||
|
||||
fn next_line(&mut self) -> Option<String> {
|
||||
let mut res = String::new();
|
||||
match self.file.read_line(&mut res) {
|
||||
match self.0.borrow_mut().file.read_line(&mut res) {
|
||||
Err(e) => {
|
||||
eprintln!("error: {e:?}");
|
||||
None
|
||||
|
|
@ -93,71 +95,51 @@ impl LogfileReader {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter_from(&mut self, start: usize) -> FilterAdapter<EntryIterator<'_>> {
|
||||
FilterAdapter {
|
||||
filters: self.filters.clone(),
|
||||
inner: EntryIterator {
|
||||
curr: start,
|
||||
reader: self,
|
||||
},
|
||||
fn fill_buf_to_access_index(&mut self, n: usize) -> Option<Rc<LogEntry>> {
|
||||
while self.0.borrow().cached_entries.len() <= n {
|
||||
let entry = self.next_entry()?;
|
||||
self.0.borrow_mut().cached_entries.push(entry);
|
||||
}
|
||||
|
||||
Some(Rc::clone(&self.0.borrow().cached_entries[n]))
|
||||
}
|
||||
|
||||
fn add_next_entry(&mut self) -> Option<()> {
|
||||
let entry = self.next_entry()?;
|
||||
self.entries.push(entry);
|
||||
Some(())
|
||||
pub fn iter(&self) -> LogFileReaderStream {
|
||||
LogFileReaderStream {
|
||||
reader: self.clone(),
|
||||
curr: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EntryIterator<'a> {
|
||||
pub struct LogFileReaderStream {
|
||||
reader: LogfileReader,
|
||||
curr: usize,
|
||||
reader: &'a mut LogfileReader,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EntryIterator<'a> {
|
||||
type Item = Rc<LogEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while self.reader.entries.len() <= self.curr {
|
||||
self.reader.add_next_entry()?;
|
||||
}
|
||||
|
||||
let res = Rc::clone(&self.reader.entries[self.curr]);
|
||||
impl LogStream for LogFileReaderStream {
|
||||
fn next(&mut self) -> Option<Rc<LogEntry>> {
|
||||
let entry = self.reader.fill_buf_to_access_index(self.curr)?;
|
||||
self.curr += 1;
|
||||
Some(res)
|
||||
|
||||
Some(entry)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterAdapter<I> {
|
||||
filters: Vec<Rc<Filter>>,
|
||||
inner: I,
|
||||
}
|
||||
|
||||
impl<I: IntoIterator> FilterAdapter<I> {
|
||||
pub fn new(file: &LogfileReader, inner: I) -> FilterAdapter<I::IntoIter> {
|
||||
Self {
|
||||
filters: file.filters.clone(),
|
||||
inner: inner.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> Iterator for FilterAdapter<I> {
|
||||
type Item = I::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
'next_entry: loop {
|
||||
let res = self.inner.next()?;
|
||||
|
||||
for filter in &self.reader.filters {
|
||||
if let FilterKind::Remove = filter.kind
|
||||
&& filter.matcher.matches(&res)
|
||||
{
|
||||
continue 'next_entry;
|
||||
}
|
||||
}
|
||||
break Some(res);
|
||||
fn prev(&mut self) -> Option<Rc<LogEntry>> {
|
||||
if self.curr == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let entry = self.reader.fill_buf_to_access_index(self.curr)?;
|
||||
self.curr -= 1;
|
||||
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
fn clone(&self) -> Box<dyn LogStream> {
|
||||
Box::new(Self {
|
||||
reader: self.reader.clone(),
|
||||
curr: self.curr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue