diff --git a/src/formats.rs b/src/formats.rs index 7ec1af9..47d86d7 100644 --- a/src/formats.rs +++ b/src/formats.rs @@ -1,51 +1,65 @@ -use std::io; -use std::io::Write; +use std::io::{self, Write}; use crate::Findings; use crate::scanerror::ScanError; use std::path::PathBuf; use snailquote::escape; +#[cfg(unix)] +use std::os::unix::ffi::OsStrExt; + +#[cfg(windows)] +use std::os::windows::ffi::OsStrExt; + type Entries = [Result]; +fn write_pathbuf(f: &mut W, path: &PathBuf) -> io::Result<()> { + match path.to_str() { + Some(string) => {write!(f, "{}", escape(string))} + None => { + write!(f, "'")?; + #[cfg(unix)] + f.write_all(&*path.as_os_str().as_bytes())?; + #[cfg(windows)] + f.write_all(&*path.as_os_str().encode_wide().collect())?; // TODO: TEST THIS + write!(f, "'") + } + } +} + pub trait Format { fn new() -> Self; - fn rename(&self, f: &mut T, from: &str, to: &str) -> io::Result<()>; - fn no_known_extension(&self, f: &mut T, path: &str) -> io::Result<()>; - fn unreadable(&self, f: &mut T, path: &str) -> io::Result<()>; - fn unknown_type(&self, f: &mut T, path: &str) -> io::Result<()>; + fn rename(&self, f: &mut W, from: &PathBuf, to: &PathBuf) -> io::Result<()>; + fn no_known_extension(&self, f: &mut W, path: &PathBuf) -> io::Result<()>; + fn unreadable(&self, f: &mut W, path: &PathBuf) -> io::Result<()>; + fn unknown_type(&self, f: &mut W, path: &PathBuf) -> io::Result<()>; - fn write_all(&self, entries: &Entries, f: &mut T) -> io::Result<()> { + fn write_all(&self, entries: &Entries, f: &mut W) -> io::Result<()> { // TODO: clean this up - it's horrifying for entry in entries { match entry { Ok(finding) => { // the file was successfully scanned, and a mimetype was detected if !finding.valid { - // the file's extension is wrong! - match finding.recommended_extension() { - Some(ext) => { - // there's a known extension for this mimetype!! - self.rename( - f, - &finding.file.to_string_lossy(), - &finding.file.with_extension(ext.as_str()).to_string_lossy() - )? - } - None => { - // unfortunately, there's no known extension for this mimetype :( - self.no_known_extension(f, &finding.file.to_string_lossy())? - } - } + // 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()) + )? + } else { + self.no_known_extension(f, &finding.file)? + } } } Err(error) => { // something went wrong 0uo match error.0 { // failed to read the file - ScanError::File => self.unreadable(f, &error.1.to_string_lossy())?, + 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.to_string_lossy())? + ScanError::Mime => self.unknown_type(f, &error.1)? } } } @@ -56,24 +70,35 @@ pub trait Format { pub struct Script {} impl Format for Script { + // TODO: begin write_all output with "#!/bin/sh" or w/e fn new() -> Self { return Script {} } - fn rename(&self, f: &mut T, from: &str, to: &str) -> io::Result<()> { - // TODO: string escaping aaaaaaAAAAAAAAAA - writeln!(f, "mv -v -i -- {} {}", escape(from), escape(to)) + fn rename(&self, f: &mut W, from: &PathBuf, to: &PathBuf) -> io::Result<()> { + // TODO: surely there's a better way... + write!(f, "mv -v -i -- ")?; + write_pathbuf(f, from)?; + write!(f, " ")?; + write_pathbuf(f, to)?; + write!(f, "\n") } - fn no_known_extension(&self, f: &mut T, path: &str) -> io::Result<()> { - writeln!(f, "echo No known extension for {}!", escape(path)) + fn no_known_extension(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { + write!(f, "echo No known extension for ")?; + write_pathbuf(f, path)?; + write!(f, "\n") } - fn unreadable(&self, f: &mut T, path: &str) -> io::Result<()> { - writeln!(f, "# Failed to read {}", escape(path)) + fn unreadable(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { + write!(f, "# Failed to read ")?; + write_pathbuf(f, path)?; + write!(f, "\n") } - fn unknown_type(&self, f: &mut T, path: &str) -> io::Result<()> { - writeln!(f, "# Failed to detect mime type for {}", escape(path)) + fn unknown_type(&self, f: &mut W, path: &PathBuf) -> io::Result<()> { + write!(f, "# Failed to detect mime type for ")?; + write_pathbuf(f, path)?; + write!(f, "\n") } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index fdd1599..7a2b183 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,7 @@ use log::{debug, trace, info, warn}; use rayon::prelude::*; use std::fmt::{self, Display}; use xdg_mime::SharedMimeInfo; -use std::io::stdout; +use std::io::{stdout, BufWriter}; use crate::parameters::OutputFormat; use crate::scanerror::ScanError; use crate::formats::{Script, Format}; @@ -204,7 +204,7 @@ fn main() { match args.output_format { OutputFormat::Script => { let s = Script::new(); - s.write_all(&results, &mut stdout().lock()).expect("failed to ouptput"); + s.write_all(&results, &mut BufWriter::new(stdout().lock())).expect("failed to output"); }, OutputFormat::Text => debug!("eewr") }