diff --git a/rusftmt.toml b/rusftmt.toml new file mode 100644 index 0000000..8e5edff --- /dev/null +++ b/rusftmt.toml @@ -0,0 +1,4 @@ +max_width = 120 +hard_tabs = true +tab_spaces = 2 +newline_style = "Unix" \ No newline at end of file diff --git a/src/findings.rs b/src/findings.rs index 2fb2a11..e4c11a5 100644 --- a/src/findings.rs +++ b/src/findings.rs @@ -1,8 +1,10 @@ use std::path::PathBuf; -use crate::inspectors::mime_extension_lookup; + use mime_guess::Mime; use smartstring::alias::String; +use crate::inspectors::mime_extension_lookup; + pub struct Findings { pub file: PathBuf, // TODO: replace with Path???? <'a> and all that pub valid: bool, @@ -11,7 +13,6 @@ pub struct Findings { impl Findings { pub fn recommended_extension(&self) -> Option { - mime_extension_lookup(self.mime.clone()) - .map(|extensions| extensions[0].to_owned()) + mime_extension_lookup(self.mime.clone()).map(|extensions| extensions[0].to_owned()) } } diff --git a/src/formats.rs b/src/formats.rs index a5744d3..57c5f76 100644 --- a/src/formats.rs +++ b/src/formats.rs @@ -16,13 +16,15 @@ type Entries = [Result]; fn write_pathbuf(f: &mut W, path: &PathBuf) -> io::Result<()> { match path.to_str() { - Some(string) => { write!(f, "{}", escape(string)) } + Some(string) => { + write!(f, "{}", escape(string)) + } None => { write!(f, "'")?; #[cfg(unix)] - f.write_all(&*path.as_os_str().as_bytes())?; + f.write_all(&*path.as_os_str().as_bytes())?; #[cfg(windows)] - f.write_all(&*path.as_os_str().encode_wide().collect())?; // TODO: TEST THIS + f.write_all(&*path.as_os_str().encode_wide().collect())?; // TODO: TEST THIS write!(f, "'") } } @@ -48,11 +50,7 @@ pub trait Format { if !finding.valid { // the file's extension is wrong - check for known extension if let Some(ext) = finding.recommended_extension() { - self.rename( - f, - &finding.file, - &finding.file.with_extension(ext.as_str()), - )? + self.rename(f, &finding.file, &finding.file.with_extension(ext.as_str()))? } else { self.no_known_extension(f, &finding.file)? } @@ -64,7 +62,7 @@ pub trait Format { // failed to read the file ScanError::File => self.unreadable(f, &error.1)?, // file was read successfully, but we couldn't determine a mimetype - ScanError::Mime => self.unknown_type(f, &error.1)? + ScanError::Mime => self.unknown_type(f, &error.1)?, } } } @@ -77,7 +75,9 @@ pub trait Format { pub struct Script {} impl Format for Script { - fn new() -> Self { Self {} } + fn new() -> Self { + Self {} + } fn rename(&self, f: &mut W, from: &PathBuf, to: &PathBuf) -> io::Result<()> { // TODO: surely there's a better way... @@ -85,32 +85,36 @@ impl Format for Script { write_pathbuf(f, from)?; write!(f, " ")?; write_pathbuf(f, to)?; - writeln!(f, ) + writeln!(f,) } fn no_known_extension(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { write!(f, "echo No known extension for ")?; write_pathbuf(f, path)?; - writeln!(f, ) + writeln!(f,) } fn unreadable(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { write!(f, "# Failed to read ")?; write_pathbuf(f, path)?; - writeln!(f, ) + writeln!(f,) } fn unknown_type(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { write!(f, "# Failed to detect mime type for ")?; write_pathbuf(f, path)?; - writeln!(f, ) + writeln!(f,) } fn header(&self, _: &Entries, f: &mut W) -> io::Result<()> { - write!(f, "#!/usr/bin/env sh\n\nGenerated by fif {}.\n\n", VERSION.unwrap_or("???")) + write!( + f, + "#!/usr/bin/env sh\n\nGenerated by fif {}.\n\n", + VERSION.unwrap_or("???") + ) } fn footer(&self, _: &Entries, f: &mut W) -> io::Result<()> { writeln!(f, "\necho Done.") } -} \ No newline at end of file +} diff --git a/src/inspectors.rs b/src/inspectors.rs index a1e5272..fb66d3f 100644 --- a/src/inspectors.rs +++ b/src/inspectors.rs @@ -21,7 +21,7 @@ use crate::mimedb::MimeDb; // at least 265 bytes to identify a tar file. const BUF_SIZE: usize = 512; -pub fn mime_type(db: &T, path: &Path) -> io::Result, > { +pub fn mime_type(db: &T, path: &Path) -> io::Result> { // attempt to read up to the BUF_SIZE bytes of the file let mut buffer = [0; 64]; @@ -30,8 +30,7 @@ pub fn mime_type(db: &T, path: &Path) -> io::Result, > { // this lint can be ignored: it's okay if the file isn't long enough to fill the buffer, as we only care about the // first few bytes for the purpose of mime sniffing #[allow(clippy::unused_io_amount)] - file.read(&mut buffer)?; - + file.read(&mut buffer)?; let r = db.get_type(&buffer); if r.is_some() { @@ -61,4 +60,3 @@ cached! { } } } - diff --git a/src/main.rs b/src/main.rs index 1a49734..f2fe065 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use clap::Clap; use log::{debug, info, trace, warn}; use once_cell::sync::OnceCell; #[cfg(feature = "multi-threaded")] - use rayon::prelude::*; +use rayon::prelude::*; use smartstring::alias::String; use walkdir::{DirEntry, WalkDir}; @@ -31,18 +31,18 @@ use crate::mimedb::MimeDb; use crate::parameters::OutputFormat; use crate::scanerror::ScanError; -mod parameters; -mod inspectors; -mod formats; -mod scanerror; mod findings; +mod formats; +mod inspectors; mod mimedb; +mod parameters; +mod scanerror; #[cfg(feature = "infer-backend")] - static MIMEDB: OnceCell = OnceCell::new(); +static MIMEDB: OnceCell = OnceCell::new(); #[cfg(feature = "xdg-mime-backend")] - static MIMEDB: OnceCell = OnceCell::new(); +static MIMEDB: OnceCell = OnceCell::new(); // TODO: test if this actually works on a windows machine #[cfg(windows)] @@ -50,14 +50,17 @@ fn is_hidden(entry: &DirEntry) -> bool { use std::os::windows::prelude::*; std::fs::metadata(entry) // try to get metadata for file .map_or( - false, // if getting metadata/attributes fails, assume it's not hidden + false, // if getting metadata/attributes fails, assume it's not hidden |f| f.file_attributes() & 0x2 > 0, // flag for hidden - https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants ) } #[cfg(not(windows))] fn is_hidden(entry: &DirEntry) -> bool { - entry.file_name().to_str().map_or(false, |f| f.starts_with('.') && f != ".") + entry + .file_name() + .to_str() + .map_or(false, |f| f.starts_with('.') && f != ".") } fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool { @@ -73,7 +76,9 @@ fn wanted_file(args: ¶meters::Parameters, entry: &DirEntry) -> bool { let ext = extension_from_path(entry.path()); - if ext.is_none() { return false; } // don't scan files without extensions. TODO - this should be configurable + if ext.is_none() { + return false; + } // don't scan files without extensions. TODO - this should be configurable if let Some(extensions) = &args.extensions { // if the user has specified a list of extensions to check against, make sure this file ends in one of them. @@ -117,7 +122,7 @@ fn scan_file(entry: &DirEntry) -> Result { // there is a known set of extensions for this mimetype, but the file has no extension Some(_) => false, // there is no known set of extensions for this mimetype -- assume it's correct - None => true + None => true, }; Ok(Findings { @@ -128,25 +133,25 @@ fn scan_file(entry: &DirEntry) -> Result { } fn scan_from_walkdir(entries: Vec) -> Vec> { - #[cfg(feature = "multi-threaded")] { + #[cfg(feature = "multi-threaded")] + { // rather than using a standard par_iter, split the entries into chunks of 32 first. // this allows each spawned thread to handle 32 files before before closing, rather than creating a new thread for // each file. this leads to a pretty substantial speedup that i'm pretty substantially happy about 0u0 entries .par_chunks(32) // split into chunks of 32 - .flat_map(|chunk| chunk // return Vec<...> instead of Chunk> - .iter() // iter over the chunk, which is a slice of DirEntry structs - .map(|entry| scan_file(entry)) - .collect::>() - ) + .flat_map(|chunk| { + chunk // return Vec<...> instead of Chunk> + .iter() // iter over the chunk, which is a slice of DirEntry structs + .map(|entry| scan_file(entry)) + .collect::>() + }) .collect() } - #[cfg(not(feature = "multi-threaded"))] { - entries - .iter() - .map(|entry: &DirEntry| scan_file(entry)) - .collect() + #[cfg(not(feature = "multi-threaded"))] + { + entries.iter().map(|entry: &DirEntry| scan_file(entry)).collect() } } @@ -161,10 +166,16 @@ fn main() { .init(); #[cfg(feature = "infer-backend")] - MIMEDB.set(mimedb::InferDb::init()).or(Err("Failed to initialise MIMEDB")).unwrap(); + MIMEDB + .set(mimedb::InferDb::init()) + .or(Err("Failed to initialise MIMEDB")) + .unwrap(); #[cfg(feature = "xdg-mime-backend")] - MIMEDB.set(mimedb::XdgDb::init()).or(Err("Failed to initialise MIMEDB")).unwrap(); + MIMEDB + .set(mimedb::XdgDb::init()) + .or(Err("Failed to initialise MIMEDB")) + .unwrap(); debug!("Iterating directory: {:?}", args.dirs); @@ -183,21 +194,26 @@ fn main() { match result { Ok(r) => { if !r.valid { - info!("{:?} should have file extension {}", r.file, r.recommended_extension().unwrap()) + info!( + "{:?} should have file extension {}", + r.file, + r.recommended_extension().unwrap() + ) } else { trace!("{:?} is totally fine", r.file) } } - Err(f) => warn!("{:#?}: Error 0uo - {}", f.1, f.0) + Err(f) => warn!("{:#?}: Error 0uo - {}", f.1, f.0), } } match args.output_format { OutputFormat::Script => { let s = Script::new(); - s.write_all(&results, &mut BufWriter::new(stdout().lock())).expect("failed to output"); + s.write_all(&results, &mut BufWriter::new(stdout().lock())) + .expect("failed to output"); } - OutputFormat::Text => todo!() + OutputFormat::Text => todo!(), } debug!("Done"); diff --git a/src/mimedb.rs b/src/mimedb.rs index 714bd7d..c080718 100644 --- a/src/mimedb.rs +++ b/src/mimedb.rs @@ -1,6 +1,7 @@ -use mime_guess::Mime; #[cfg(feature = "infer-backend")] - use std::str::FromStr; +use std::str::FromStr; + +use mime_guess::Mime; pub trait MimeDb { fn init() -> Self; @@ -9,7 +10,7 @@ pub trait MimeDb { #[cfg(feature = "infer-backend")] pub struct InferDb { - db: infer::Infer + db: infer::Infer, } #[cfg(feature = "infer-backend")] @@ -17,11 +18,8 @@ impl MimeDb for InferDb { fn init() -> Self { let mut info = infer::Infer::new(); // add a random file type just to make sure adding works and such - info.add( - "image/jpeg2000", - ".jp2", - |buf| { - buf.len() > 23 + info.add("image/jpeg2000", ".jp2", |buf| { + buf.len() > 23 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x00 @@ -38,8 +36,7 @@ impl MimeDb for InferDb { && buf[21] == 0x70 && buf[22] == 0x32 && buf[23] == 0x20 - } - ); + }); // unmut let info = info; @@ -48,26 +45,24 @@ impl MimeDb for InferDb { } fn get_type(&self, data: &[u8]) -> Option { - self.db - .get(data) - .map(|f| Mime::from_str(f.mime_type()).unwrap()) + self.db.get(data).map(|f| Mime::from_str(f.mime_type()).unwrap()) } } #[cfg(feature = "xdg-mime-backend")] pub struct XdgDb { - db: xdg_mime::SharedMimeInfo + db: xdg_mime::SharedMimeInfo, } #[cfg(feature = "xdg-mime-backend")] impl MimeDb for XdgDb { fn init() -> Self { Self { - db: xdg_mime::SharedMimeInfo::new() + db: xdg_mime::SharedMimeInfo::new(), } } fn get_type(&self, data: &[u8]) -> Option { self.db.get_mime_type_for_data(&data).map(|m| m.0) } -} \ No newline at end of file +} diff --git a/src/scanerror.rs b/src/scanerror.rs index ff11ec4..ccb61ae 100644 --- a/src/scanerror.rs +++ b/src/scanerror.rs @@ -2,16 +2,18 @@ use std::fmt::{Display, Formatter, Result}; pub enum ScanError { File, - Mime + Mime, } impl Display for ScanError { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "{}", - match self { - Self::File => "Couldn't read file", - Self::Mime => "Couldn't determine mime type" - } + write!( + f, + "{}", + match self { + Self::File => "Couldn't read file", + Self::Mime => "Couldn't determine mime type", + } ) } -} \ No newline at end of file +}