]> code.octet-stream.net Git - hashgood/blobdiff - src/display.rs
Update README and metadata in preparation for future 0.5.0 release
[hashgood] / src / display.rs
index 2cc940adca4d8883274ec1663c13d6a89d3b3b2a..1a3b243cfdfda2e708550126bb2c2799504e44c6 100644 (file)
@@ -21,7 +21,7 @@ fn get_stdout(no_colour: bool) -> StandardStream {
 }
 
 fn write_filename(mut stdout: &mut StandardStream, filename: &str) -> PrintResult {
 }
 
 fn write_filename(mut stdout: &mut StandardStream, filename: &str) -> PrintResult {
-    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?;
+    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
     write!(&mut stdout, "{}", filename_display(filename))?;
     stdout.reset()?;
     Ok(())
     write!(&mut stdout, "{}", filename_display(filename))?;
     stdout.reset()?;
     Ok(())
@@ -30,49 +30,70 @@ fn write_filename(mut stdout: &mut StandardStream, filename: &str) -> PrintResul
 fn write_algorithm(mut stdout: &mut StandardStream, alg: Algorithm) -> PrintResult {
     match alg {
         Algorithm::Md5 => {
 fn write_algorithm(mut stdout: &mut StandardStream, alg: Algorithm) -> PrintResult {
     match alg {
         Algorithm::Md5 => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Magenta)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Magenta)).set_bold(true))?;
             write!(&mut stdout, "MD5")?;
         }
         Algorithm::Sha1 => {
             write!(&mut stdout, "MD5")?;
         }
         Algorithm::Sha1 => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)).set_bold(true))?;
             write!(&mut stdout, "SHA-1")?;
         }
         Algorithm::Sha256 => {
             write!(&mut stdout, "SHA-1")?;
         }
         Algorithm::Sha256 => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?;
             write!(&mut stdout, "SHA-256")?;
         }
             write!(&mut stdout, "SHA-256")?;
         }
+        Algorithm::Sha512 => {
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Blue)).set_bold(true))?;
+            write!(&mut stdout, "SHA-512")?;
+        }
     }
     stdout.reset()?;
     Ok(())
 }
 
     }
     stdout.reset()?;
     Ok(())
 }
 
-fn print_hex_compare(print: &str, against: &str, mut stdout: &mut StandardStream) -> PrintResult {
-    for (p, a) in print.chars().zip(against.chars()) {
-        if p == a {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
+fn print_hex_compare(
+    print: &[u8],
+    matches: &[bool],
+    mut stdout: &mut StandardStream,
+) -> PrintResult {
+    for (p, m) in print.iter().zip(matches.iter()) {
+        if *m {
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?;
         } else {
         } else {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true))?;
         }
         }
-        write!(&mut stdout, "{}", p)?;
+        write!(&mut stdout, "{:02x}", p)?;
     }
     stdout.reset()?;
     writeln!(&mut stdout)?;
     Ok(())
 }
 
     }
     stdout.reset()?;
     writeln!(&mut stdout)?;
     Ok(())
 }
 
+fn print_pointer_line(
+    matches: &[bool],
+    marker: &str,
+    mut stdout: &mut StandardStream,
+) -> PrintResult {
+    for m in matches {
+        if *m {
+            write!(&mut stdout, "  ")?;
+        } else {
+            write!(&mut stdout, "{}{}", marker, marker)?;
+        }
+    }
+    write!(&mut stdout, "\n")?;
+    Ok(())
+}
+
 fn write_source(
     mut stdout: &mut StandardStream,
     verify_source: &VerificationSource,
     candidate_filename: &Option<String>,
 ) -> PrintResult {
 fn write_source(
     mut stdout: &mut StandardStream,
     verify_source: &VerificationSource,
     candidate_filename: &Option<String>,
 ) -> PrintResult {
-    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?;
+    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
     match &verify_source {
         VerificationSource::CommandArgument => {
             writeln!(&mut stdout, "command line argument")?;
         }
     match &verify_source {
         VerificationSource::CommandArgument => {
             writeln!(&mut stdout, "command line argument")?;
         }
-        VerificationSource::Clipboard => {
-            writeln!(&mut stdout, "pasted from clipboard")?;
-        }
         VerificationSource::RawFile(raw_path) => match raw_path.as_str() {
             "-" => {
                 writeln!(&mut stdout, "from standard input")?;
         VerificationSource::RawFile(raw_path) => match raw_path.as_str() {
             "-" => {
                 writeln!(&mut stdout, "from standard input")?;
@@ -103,6 +124,14 @@ fn write_source(
     Ok(())
 }
 
     Ok(())
 }
 
+fn calculate_match_indices(bytes1: &[u8], bytes2: &[u8]) -> Vec<bool> {
+    bytes1
+        .iter()
+        .zip(bytes2.iter())
+        .map(|(b1, b2)| b1 == b2)
+        .collect()
+}
+
 pub fn print_hash(
     hash: &Hash,
     verify_hash: Option<&CandidateHash>,
 pub fn print_hash(
     hash: &Hash,
     verify_hash: Option<&CandidateHash>,
@@ -117,19 +146,26 @@ pub fn print_hash(
     writeln!(&mut stdout)?;
 
     // Handle basic case first - nothing to compare it to
     writeln!(&mut stdout)?;
 
     // Handle basic case first - nothing to compare it to
-    let hash_hex = hex::encode(&hash.bytes);
     let verify_hash = match verify_hash {
         None => {
     let verify_hash = match verify_hash {
         None => {
-            write!(&mut stdout, "{}\n\n", hash_hex)?;
+            write!(&mut stdout, "{}\n\n", hex::encode(&hash.bytes))?;
             return Ok(());
         }
         Some(verify_hash) => verify_hash,
     };
             return Ok(());
         }
         Some(verify_hash) => verify_hash,
     };
-    let other_hex = hex::encode(&verify_hash.bytes);
 
     // Do a top-to-bottom comparison
 
     // Do a top-to-bottom comparison
-    print_hex_compare(&hash_hex, &other_hex, &mut stdout)?;
-    print_hex_compare(&other_hex, &hash_hex, &mut stdout)?;
+    let matches = calculate_match_indices(&hash.bytes, &verify_hash.bytes);
+    let any_wrong = matches.iter().any(|m| !*m);
+
+    if any_wrong && no_colour {
+        print_pointer_line(&matches, "v", &mut stdout)?;
+    }
+    print_hex_compare(&hash.bytes, &matches, &mut stdout)?;
+    print_hex_compare(&verify_hash.bytes, &matches, &mut stdout)?;
+    if any_wrong && no_colour {
+        print_pointer_line(&matches, "^", &mut stdout)?;
+    }
 
     // Show the source of our hash
     if let Some(source) = verify_source {
 
     // Show the source of our hash
     if let Some(source) = verify_source {
@@ -173,15 +209,15 @@ pub fn print_match_level(match_level: MatchLevel, no_colour: bool) -> PrintResul
     write!(&mut stdout, "Result: ")?;
     match match_level {
         MatchLevel::Ok => {
     write!(&mut stdout, "Result: ")?;
     match match_level {
         MatchLevel::Ok => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?;
             writeln!(&mut stdout, "OK")?;
         }
         MatchLevel::Maybe => {
             writeln!(&mut stdout, "OK")?;
         }
         MatchLevel::Maybe => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
             writeln!(&mut stdout, "MAYBE")?;
         }
         MatchLevel::Fail => {
             writeln!(&mut stdout, "MAYBE")?;
         }
         MatchLevel::Fail => {
-            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
+            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true))?;
             writeln!(&mut stdout, "FAIL")?;
         }
     }
             writeln!(&mut stdout, "FAIL")?;
         }
     }