use std::path::{Path, PathBuf};
use crate::git_tree::{Stream, fold_stream};
pub(super) struct Open {
pub(super) path: PathBuf,
offset: u64,
partial: Vec<u8>,
}
impl Open {
pub(super) fn at(path: PathBuf) -> Self {
Self {
path,
offset: 0,
partial: Vec::new(),
}
}
pub(super) fn read_appended(&mut self) -> Option<Stream> {
let len = std::fs::metadata(&self.path).ok()?.len();
if len < self.offset {
self.offset = 0;
self.partial.clear();
}
if len == self.offset {
return None;
}
let fresh = read_from(&self.path, self.offset)?;
self.offset = len.min(self.offset + fresh.len() as u64);
self.partial.extend_from_slice(&fresh);
let end = self.partial.iter().rposition(|&b| b == b'\n')? + 1;
let folded = fold_stream(self.partial.get(..end)?);
self.partial.drain(..end);
Some(folded)
}
}
fn read_from(path: &Path, offset: u64) -> Option<Vec<u8>> {
use std::io::{Read, Seek, SeekFrom};
let mut file = std::fs::File::open(path).ok()?;
file.seek(SeekFrom::Start(offset)).ok()?;
let mut fresh = Vec::new();
file.read_to_end(&mut fresh).ok()?;
Some(fresh)
}