]>
code.octet-stream.net Git - hashgood/blob - src/display.rs
1a3b243cfdfda2e708550126bb2c2799504e44c6
1 use super::{Algorithm
, CandidateHash
, Hash
, MatchLevel
, MessageLevel
, VerificationSource
};
4 use termcolor
::{Color
, ColorChoice
, ColorSpec
, StandardStream
, WriteColor
};
6 pub type PrintResult
= Result
<(), Box
<dyn Error
>>;
8 fn filename_display(filename
: &str) -> &str {
10 return "standard input";
15 fn get_stdout(no_colour
: bool
) -> StandardStream
{
17 StandardStream
::stdout(ColorChoice
::Never
)
19 StandardStream
::stdout(ColorChoice
::Always
)
23 fn write_filename(mut stdout
: &mut StandardStream
, filename
: &str) -> PrintResult
{
24 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Yellow
)).set_bold(true))?
;
25 write
!(&mut stdout
, "{}", filename_display(filename
))?
;
30 fn write_algorithm(mut stdout
: &mut StandardStream
, alg
: Algorithm
) -> PrintResult
{
33 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Magenta
)).set_bold(true))?
;
34 write
!(&mut stdout
, "MD5")?
;
37 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Cyan
)).set_bold(true))?
;
38 write
!(&mut stdout
, "SHA-1")?
;
40 Algorithm
::Sha256
=> {
41 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Green
)).set_bold(true))?
;
42 write
!(&mut stdout
, "SHA-256")?
;
44 Algorithm
::Sha512
=> {
45 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Blue
)).set_bold(true))?
;
46 write
!(&mut stdout
, "SHA-512")?
;
56 mut stdout
: &mut StandardStream
,
58 for (p
, m
) in print
.iter
().zip(matches
.iter
()) {
60 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Green
)).set_bold(true))?
;
62 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Red
)).set_bold(true))?
;
64 write
!(&mut stdout
, "{:02x}", p
)?
;
67 writeln
!(&mut stdout
)?
;
71 fn print_pointer_line(
74 mut stdout
: &mut StandardStream
,
78 write
!(&mut stdout
, " ")?
;
80 write
!(&mut stdout
, "{}{}", marker
, marker
)?
;
83 write
!(&mut stdout
, "\n")?
;
88 mut stdout
: &mut StandardStream
,
89 verify_source
: &VerificationSource
,
90 candidate_filename
: &Option
<String
>,
92 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Yellow
)).set_bold(true))?
;
93 match &verify_source
{
94 VerificationSource
::CommandArgument
=> {
95 writeln
!(&mut stdout
, "command line argument")?
;
97 VerificationSource
::RawFile(raw_path
) => match raw_path
.as_str() {
99 writeln
!(&mut stdout
, "from standard input")?
;
102 writeln
!(&mut stdout
, "from file '{}' containing raw hash", path
)?
;
105 VerificationSource
::DigestsFile(digest_path
) => match digest_path
.as_str() {
109 "'{}' from digests on standard input",
110 candidate_filename
.as_ref().unwrap
()
116 "'{}' in digests file '{}'",
117 candidate_filename
.as_ref().unwrap
(),
127 fn calculate_match_indices(bytes1
: &[u8], bytes2
: &[u8]) -> Vec
<bool
> {
131 .map(|(b1
, b2
)| b1
== b2
)
137 verify_hash
: Option
<&CandidateHash
>,
138 verify_source
: Option
<&VerificationSource
>,
141 let mut stdout
= get_stdout(no_colour
);
143 write_filename(&mut stdout
, &hash
.filename
)?
;
144 write
!(&mut stdout
, " / ")?
;
145 write_algorithm(&mut stdout
, hash
.alg
)?
;
146 writeln
!(&mut stdout
)?
;
148 // Handle basic case first - nothing to compare it to
149 let verify_hash
= match verify_hash
{
151 write
!(&mut stdout
, "{}\n\n", hex
::encode(&hash
.bytes
))?
;
154 Some(verify_hash
) => verify_hash
,
157 // Do a top-to-bottom comparison
158 let matches
= calculate_match_indices(&hash
.bytes
, &verify_hash
.bytes
);
159 let any_wrong
= matches
.iter
().any(|m
| !*m
);
161 if any_wrong
&& no_colour
{
162 print_pointer_line(&matches
, "v", &mut stdout
)?
;
164 print_hex_compare(&hash
.bytes
, &matches
, &mut stdout
)?
;
165 print_hex_compare(&verify_hash
.bytes
, &matches
, &mut stdout
)?
;
166 if any_wrong
&& no_colour
{
167 print_pointer_line(&matches
, "^", &mut stdout
)?
;
170 // Show the source of our hash
171 if let Some(source
) = verify_source
{
172 write_source(&mut stdout
, source
, &verify_hash
.filename
)?
;
175 writeln
!(&mut stdout
)?
;
179 pub fn print_messages(messages
: Vec
<(MessageLevel
, String
)>, no_colour
: bool
) -> PrintResult
{
180 let mut stdout
= get_stdout(no_colour
);
182 for (level
, msg
) in &messages
{
184 MessageLevel
::Error
=> {
185 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Red
)))?
;
186 write
!(&mut stdout
, "(error) ")?
;
188 MessageLevel
::Warning
=> {
189 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Yellow
)))?
;
190 write
!(&mut stdout
, "(warning) ")?
;
192 MessageLevel
::Note
=> {
193 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Cyan
)))?
;
194 write
!(&mut stdout
, "(note) ")?
;
198 writeln
!(&mut stdout
, "{}", msg
)?
;
200 if !messages
.is
_empty
() {
201 writeln
!(&mut stdout
)?
207 pub fn print_match_level(match_level
: MatchLevel
, no_colour
: bool
) -> PrintResult
{
208 let mut stdout
= get_stdout(no_colour
);
209 write
!(&mut stdout
, "Result: ")?
;
212 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Green
)).set_bold(true))?
;
213 writeln
!(&mut stdout
, "OK")?
;
215 MatchLevel
::Maybe
=> {
216 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Yellow
)).set_bold(true))?
;
217 writeln
!(&mut stdout
, "MAYBE")?
;
219 MatchLevel
::Fail
=> {
220 stdout
.set_color(ColorSpec
::new().set_fg(Some(Color
::Red
)).set_bold(true))?
;
221 writeln
!(&mut stdout
, "FAIL")?
;