haggis-rs/src/listing_stream.rs
2024-01-17 01:58:36 -05:00

65 lines
1.8 KiB
Rust

use {
crate::{listing::Kind, Error, Listing, MAGIC},
std::{
io::{ErrorKind, Read, Seek},
iter::Iterator,
},
};
/// An iterator over `Listing` items, used for displaying the contents of a
/// *Haggis* archive
#[derive(Debug)]
pub struct ListingStream<R: Read + Send> {
pub length: u32,
reader: R,
}
impl<R: Read + Send + Seek> Iterator for ListingStream<R> {
type Item = Result<Listing, Error>;
fn next(&mut self) -> Option<Self::Item> {
match Listing::read(&mut self.reader) {
Err(Error::Io(e)) if e.kind() == ErrorKind::UnexpectedEof => None,
Ok(f) => match f.kind {
Kind::Eof => None,
_ => Some(Ok(f)),
},
x => Some(x),
}
}
}
impl<R: Read + Send + Seek> ListingStream<R> {
/// Creates a new `ListingStream` from the given reader,
/// which should be a stream of bytes making up a valid Haggis
/// archive.
///# Errors
/// Can return `Error` if an io error occurs or if the arvhice
/// is incorrectly formatted
pub fn new(mut reader: R) -> Result<Self, Error> {
let mut buf = [0; 11];
reader.read_exact(&mut buf)?;
let length = u32::from_le_bytes(buf[7..].try_into()?);
if buf[0..7] == MAGIC {
Ok(Self { length, reader })
} else {
Err(Error::InvalidMagic)
}
}
/// Creates a `Vec` of `Listing` structs representing every `Node`
/// making up the archive
/// # Errors
/// Can return `Error` if an io error occurs or if the archive is
/// incorrectly formatted
pub fn list(&mut self) -> Result<Vec<Listing>, Error> {
let mut list = vec![];
for listing in self {
let listing = listing?;
list.push(listing);
}
list.sort_unstable();
Ok(list)
}
}