diff --git a/src/lib.rs b/src/lib.rs index 4c6a88f..aefd341 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod error; mod file; mod filetype; mod listing; +mod listing_stream; pub(crate) mod nix; mod node; mod special; @@ -28,6 +29,7 @@ pub use { file::File, filetype::FileType, listing::Listing, + listing_stream::ListingStream, node::Node, special::Special, stream::Stream, diff --git a/src/listing.rs b/src/listing.rs index 090f0d4..0a84422 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -7,7 +7,7 @@ use { }, }; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum Kind { Normal(u64), HardLink(String), @@ -80,7 +80,7 @@ impl Kind { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct Listing { pub name: String, pub uid: u32, @@ -92,11 +92,17 @@ pub struct Listing { impl PartialOrd for Listing { fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Listing { + fn cmp(&self, other: &Self) -> Ordering { match (&self.kind, &other.kind) { - (Kind::Directory, Kind::Directory) => self.name.partial_cmp(&other.name), - (Kind::Directory, _) => Some(Ordering::Less), - (_, Kind::Directory) => Some(Ordering::Greater), - _ => self.name.partial_cmp(&other.name), + (Kind::Directory, Kind::Directory) => self.name.cmp(&other.name), + (Kind::Directory, _) => Ordering::Less, + (_, Kind::Directory) => Ordering::Greater, + _ => self.name.cmp(&other.name), } } } diff --git a/src/listing_stream.rs b/src/listing_stream.rs new file mode 100644 index 0000000..0e215a3 --- /dev/null +++ b/src/listing_stream.rs @@ -0,0 +1,51 @@ +use { + crate::{listing::Kind, Error, Listing, MAGIC}, + std::{ + io::{ErrorKind, Read, Seek}, + iter::Iterator, + }, +}; + +#[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 { + 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) + } + } + + pub fn list(&mut self) -> Result, Error> { + let mut list = vec![]; + for listing in self { + let listing = listing?; + list.push(listing); + } + list.sort(); + Ok(list) + } +} diff --git a/src/special.rs b/src/special.rs index e36e220..9eab7db 100644 --- a/src/special.rs +++ b/src/special.rs @@ -4,7 +4,7 @@ use { }; /// Represents the major and minor numbers of a Unix special Device node -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct Special { pub major: u32, pub minor: u32, diff --git a/src/stream.rs b/src/stream.rs index bf574bf..80da367 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,5 +1,3 @@ -use crate::MAGIC; - #[cfg(feature = "parallel")] use { crate::FileType, @@ -7,7 +5,7 @@ use { std::sync::mpsc::Sender, }; use { - crate::{Error, Node}, + crate::{Error, Node, MAGIC}, std::{ io::{ErrorKind, Read}, iter::Iterator,