From 9531c0268a5cb035df74472710dc7b6af17e5841 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Sat, 23 Dec 2023 19:03:12 -0500 Subject: [PATCH] Implement Display and PartialOrd for Listing struct --- src/listing.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++- src/special.rs | 4 +- src/stream.rs | 2 +- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/listing.rs b/src/listing.rs index 8d7f0a5..a29483e 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -1,9 +1,11 @@ +use std::fmt; + use { crate::{filetype::Flag, Error, Special}, std::io::{Read, Seek, SeekFrom}, }; -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum Kind { Normal(u64), HardLink(String), @@ -16,6 +18,7 @@ pub enum Kind { } impl Kind { + #[allow(clippy::cast_possible_wrap)] fn read(reader: &mut R, flag: Flag) -> Result { match flag { Flag::Normal => { @@ -82,7 +85,7 @@ impl Kind { } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct Listing { pub name: String, pub uid: u32, @@ -92,7 +95,99 @@ pub struct Listing { pub kind: Kind, } +impl PartialOrd for Listing { + fn partial_cmp(&self, other: &Self) -> Option { + if let (Kind::Directory, Kind::Directory) = (&self.kind, &other.kind) { + self.name.partial_cmp(&other.name) + } else if let Kind::Directory = self.kind { + Some(std::cmp::Ordering::Greater) + } else if let Kind::Directory = other.kind { + Some(std::cmp::Ordering::Less) + } else { + self.name.partial_cmp(&other.name) + } + } +} + +impl fmt::Display for Listing { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}{}{}{}{}{}{}{}{}{} {}:{} {:>10}", + match self.kind { + Kind::Normal(_) => "-", + Kind::HardLink(_) => "L", + Kind::SoftLink(_) => "l", + Kind::Directory => "d", + Kind::Character(_) => "c", + Kind::Block(_) => "b", + Kind::Fifo => "p", + Kind::Eof => return Ok(()), + }, + match self.mode { + m if m & 0o400 != 0 => "r", + _ => "-", + }, + match self.mode { + m if m & 0o200 != 0 => "w", + _ => "-", + }, + match self.mode { + m if m & 0o4100 != 0 => "S", + m if m & 0o100 != 0 => "x", + _ => "-", + }, + match self.mode { + m if m & 0o40 != 0 => "r", + _ => "-", + }, + match self.mode { + m if m & 0o20 != 0 => "w", + _ => "-", + }, + match self.mode { + m if m & 0o2010 != 0 => "S", + m if m & 0o10 != 0 => "x", + _ => "-", + }, + match self.mode { + m if m & 0o4 != 0 => "r", + _ => "-", + }, + match self.mode { + m if m & 0o2 != 0 => "w", + _ => "-", + }, + match self.mode { + m if m & 0o1001 != 0 => "t", + m if m & 0o1 != 0 => "x", + _ => "-", + }, + self.uid, + self.gid, + match self.kind { + Kind::Normal(s) => s, + _ => 0, + }, + )?; + match self.kind { + Kind::Directory | Kind::Fifo | Kind::Normal(_) => write!(f, "{}", self.name), + Kind::HardLink(ref tgt) => write!(f, "{}=>{}", self.name, tgt), + Kind::SoftLink(ref tgt) => write!(f, "{}->{}", self.name, tgt), + Kind::Character(ref sp) | Kind::Block(ref sp) => { + write!(f, "{} {},{}", self.name, sp.major, sp.minor) + } + Kind::Eof => unreachable!(), + } + } +} + impl Listing { + /// Reads all metadata from a haggis Node without reading the file's actual + /// data. + /// # Errors + /// Can return an error if IO fails + #[allow(clippy::similar_names)] pub fn read(reader: &mut R) -> Result { let mut len = [0; 2]; reader.read_exact(&mut len)?; diff --git a/src/special.rs b/src/special.rs index a4cb07f..e36e220 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)] +#[derive(Debug, PartialEq)] pub struct Special { pub major: u32, pub minor: u32, @@ -32,7 +32,7 @@ impl Special { pub(super) fn from_rdev(rdev: u64) -> Self { Self { major: ((rdev >> 8) & 0xff) as u32, - minor: (rdev & 0xffff00ff) as u32, + minor: (rdev & 0xffff_00ff) as u32, } } diff --git a/src/stream.rs b/src/stream.rs index 10e2c2a..bf574bf 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -63,7 +63,7 @@ impl Stream { } } - /// Extracts and archive + /// Extracts an archive /// # Errors /// Returns `crate::Error` if io fails or several other error conditions pub fn extract(&mut self, prefix: Option<&str>) -> Result<(), Error> {