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 { pub length: u32, reader: R, } impl Iterator for ListingStream { type Item = Result; fn next(&mut self) -> Option { 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 ListingStream { /// 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 { 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, Error> { let mut list = vec![]; for listing in self { let listing = listing?; list.push(listing); } list.sort_unstable(); Ok(list) } }