From ae099d94aa2b7839caba7f90645234305ce56660 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Sat, 8 Apr 2023 11:44:09 -0400 Subject: [PATCH] Fix Header::filename() method; TODO: fix other related methods, fix Archive::get() method. --- src/tar/header.rs | 20 ++++++++++++-- src/tar/mod.rs | 67 ++++++++++++++++++++++++++++++++++++---------- src/tar/node.rs | 3 ++- test/2.tar | Bin 10240 -> 10240 bytes 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/tar/header.rs b/src/tar/header.rs index 6e22b78..bfc363a 100644 --- a/src/tar/header.rs +++ b/src/tar/header.rs @@ -117,11 +117,21 @@ impl Default for Header { } impl Header { + /// Get the filename of this archive member + /// + /// # Example + /// + /// ``` + /// use hpk_package::tar::Header; + /// + /// let header = Header::new("test/1.txt").unwrap(); + /// assert_eq!(header.filename().unwrap(), "test/1.txt"); + /// ``` pub fn filename(&self) -> Result { let mut s = String::new(); for c in self.fname { - if c != b'\0' { - write!(s, "{c}")?; + if c != 0 { + write!(s, "{}", char::from(c))?; } else { break; } @@ -217,6 +227,12 @@ impl Header { Ok(s) } + pub fn path(&self) -> Result { + let mut p = PathBuf::from(&self.prefix()?); + p.push(&self.filename()?); + Ok(p) + } + pub fn new(filename: &str) -> Result { let mut header = Header::default(); let meta = fs::symlink_metadata(filename)?; diff --git a/src/tar/mod.rs b/src/tar/mod.rs index c85010c..a84f80a 100644 --- a/src/tar/mod.rs +++ b/src/tar/mod.rs @@ -3,6 +3,8 @@ use std::{ io::{self, BufReader, Write}, }; +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; + mod error; mod header; mod node; @@ -27,7 +29,8 @@ impl Archive { Ok(buf) } - /// Write out a vector of `TarNodes` to a file or something that implements ``std::io::Write`` and ``std::io::Copy``. + /// Write out a vector of `TarNodes` to a file or something that implements + /// ``std::io::Write`` and ``std::io::Copy``. /// /// # Example /// @@ -55,8 +58,8 @@ impl Archive { Ok(written) } - /// Create a new `TarFile` struct and initialize it with a `filename` file. This will read in the file to - /// the `TarFile` struct as a `TarNode`. + /// Create a new `TarFile` struct and initialize it with a `filename` file. + /// This will read in the file to the `TarFile` struct as a `TarNode`. /// /// # Example /// @@ -71,7 +74,8 @@ impl Archive { }) } - /// Append another file to the `TarFile.file` vector. This adds a file to the internal representation of the tar file. + /// Append another file to the `TarFile.file` vector. This adds a file to the + /// internal representation of the tar file. /// /// # Example /// @@ -87,27 +91,41 @@ impl Archive { Ok(()) } - /// Open and load an external tar file into the internal `TarFile` struct. This parses and loads up all the files - /// contained within the external tar file. + /// Open and load an external tar file into the internal `TarFile` struct. This + /// parses and loads up all the files contained within the external tar file. /// /// # Example /// /// ``` /// use hpk_package::tar::Archive; /// - /// Archive::open("test/1.tar".to_string()).unwrap(); + /// Archive::open("test/1.tar").unwrap(); /// ``` - pub fn open(filename: String) -> Result { - let file = File::open(&filename)?; + pub fn open(filename: &str) -> Result { + let file = File::open(filename)?; let mut reader = BufReader::new(file); + Self::read(&mut reader) + } + + /// Read a tar archive from anything which implements `io::Read`. + /// + /// # Example + /// + /// ``` + /// use hpk_package::tar::Archive; + /// use std::{fs::File, io::BufReader}; + /// + /// let file = File::open("test/1.tar").unwrap(); + /// let mut reader = BufReader::new(file); + /// Archive::read(&mut reader).unwrap(); + /// ``` + pub fn read(mut input: T) -> Result { let mut out = Self { nodes: Vec::::new(), }; - - while let Ok(t) = Node::read(&mut reader) { + while let Ok(t) = Node::read(&mut input) { out.nodes.push(t); } - Ok(out) } @@ -119,9 +137,9 @@ impl Archive { /// use hpk_package::tar::Archive; /// /// let mut data = Archive::new("test/1.tar").unwrap(); - /// data.remove("test/1.tar".to_string()).unwrap(); + /// data.remove("test/1.tar").unwrap(); /// ``` - pub fn remove(&mut self, filename: String) -> Result { + pub fn remove(&mut self, filename: &str) -> Result { let mut name = [0u8; 100]; name[..filename.len()].copy_from_slice(filename.as_bytes()); if let Some(i) = &self.nodes.iter().position(|x| x.header.fname == name) { @@ -131,4 +149,25 @@ impl Archive { Ok(false) } + + /// Get the first node from the archive that matches the given filename. + /// + /// # Example + /// + /// ``` + /// use hpk_package::tar::Archive; + /// let archive = Archive::new("test/1.tar").unwrap(); + /// let node = archive.get("1.txt"); + /// assert!(node.is_some()); + /// ``` + pub fn get(&self, filename: &str) -> Option { + self.nodes.par_iter().find_any(|x| { + if let Ok(name) = x.header.filename() { + if &name == filename { + return true; + } + } + false + }).cloned() + } } diff --git a/src/tar/node.rs b/src/tar/node.rs index eac092c..6d31e14 100644 --- a/src/tar/node.rs +++ b/src/tar/node.rs @@ -21,7 +21,8 @@ impl Node { Ok(buf) } - /// Write out a single file within the tar to a file or something with a ``std::io::Write`` trait. + /// Write out a single file within the tar to a file or something with a + /// ``std::io::Write`` trait. pub fn write(self, mut input: T) -> Result { input.write_all(&self.header.to_bytes()?)?; let mut written = 512; diff --git a/test/2.tar b/test/2.tar index 3e7ac15362f5829b5622aa8d1698d0ed7cab964b..bc84f02484222b4020cc8cdd5186e129570ce99c 100644 GIT binary patch delta 48 zcmZn&Xb70lBWP@3W@cbw%wS+>U}|K-pkOdrkTHd)w74X(NI`)iFR>(bvLe&xMNDb{ DJ75h@ delta 50 zcmZn&Xb70lBWPq|U~FV)#$aG*XkcQ*pkOdrkTHd?w74X(NI`)iFR>&eF>kUW)5k?j FY5-Rd4jBLd