implement iterator for parsing length + data ledger

This commit is contained in:
Rob Walker 2018-07-28 15:53:17 -07:00 committed by Grimes
parent c3279c8a00
commit fc476ff979
1 changed files with 34 additions and 36 deletions

View File

@ -58,52 +58,50 @@ impl<'a, W: Write> EntryWriter<'a, W> {
} }
} }
/// Parse an escaped byte slice containing an Entry. struct EntryReader<R: BufRead> {
fn read_entry(escaped: &[u8]) -> io::Result<Entry> { reader: R,
let mut raw = Vec::with_capacity(escaped.len()); entry_bytes: Vec<u8>,
len_len: u64,
}
trace!("read_entry escaped = {:?}", escaped); impl Iterator for EntryReader<BufRead> {
type Item = io::Result<Entry>;
let mut back = false; fn next(&mut self) -> Option<io::Result<Entry>> {
for pc in escaped { let mut entry_len: usize = 0;
let mut c = *pc;
if back { let mut entry_len_bytes = [0u8; 8];
trace!("de-escaping '{}' to '{}'", c, c - b'\\');
back = false; if let Err(e) = self.reader.read_exact(&mut entry_len_bytes[..self.len_len]) {
c -= b'\\'; None // EOF, probably
} else if c == b'\\' { } else {
back = true; entry_len = bincode::deserialize(&entry_len_bytes).unwrap();
continue;
if entry_len > self.entry_bytes.len() {
self.entry_bytes.resize(entry_len);
}
if let Err(e) = self.reader.read_exact(&mut self.entry_bytes[..entry_len]) {
Some(Error::new(ErrorKind::Other, e.to_string()))
} else {
Some(
bincode::deserialize(&self.entry_bytes)
.map_err(|e| Error::new(ErrorKind::Other, e.to_string())),
)
}
} }
raw.push(c);
} }
trace!("read_entry raw = {:?}", raw);
bincode::deserialize(&raw[..]).map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
} }
/// Return an iterator for all the entries in the given file. /// Return an iterator for all the entries in the given file.
pub fn read_entries<R: BufRead>(reader: R) -> impl Iterator<Item = io::Result<Entry>> { pub fn read_entries<R: BufRead>(reader: R) -> impl Iterator<Item = io::Result<Entry>> {
let mut entry_bytes = Vec::with_capacity(BLOB_SIZE); let entry_len: usize = 0;
let mut entry_len: usize = 0;
let mut len_bytes = Vec::with_capacity(bincode::serialized_size(&entry_len).unwrap() as usize);
pub enum mode { EntryReader {
Length, reader,
Entry, entry_bytes: Vec::new(),
len_len: bincode::serialized_size(&entry_len).unwrap(),
} }
let mut mode = reader.bytes().map(|b| {
match mode {
Length -> {
}
Entry -> {
}
len = bincode::deserialize(&len_bytes).unwrap();
read_entry(&s?)
});
} }
#[cfg(test)] #[cfg(test)]