I'm currently working with the 'sha2' library.
One of the functions in my project is supposed to calculate the hash of a file using
different methods (Sha224, Sha256, Sha384, Sha512).
All of the hash methods use the trait sha2::Digest
and
all return a GenericArray<u8, Self::OutputSize>
.
However, since a generic type is used, i get following error message:
cannot add `<T as OutputSizeUser>::OutputSize` to `<T as OutputSizeUser>::OutputSize`
with this code:
use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
use std::error::Error;
use std::{env, fs, io, process};
//...
impl AutoSha {
//...
fn calc_hash<T: Digest io::Write>(&self, file_path: String) -> Result<String, Box<dyn Error>> {
let mut hasher = T::new();
let mut file = fs::File::open(file_path)?;
io::copy(&mut file, &mut hasher)?;
let hash = hasher.finalize();
Ok(format!("{:x}", hash)) // This results in the error message
}
}
//Call example:
let auto_sha: AutoSha = AutoSha::new();
let hash = auto_sha.calc_hash::<Sha256>("path/to/file".to_string());
Using, for example, Sha256::new()
instead of T::new()
works fine.
I have tried to set both 'OutputSizeUser' and 'OutputSize' as trait bounds but was unable
to find what namespace they are located in.
According to the documentation it is supposedly part of 'crypto_common' which should be included in the project as it is a dependency of 'sha2', but i was not able to include it.
Additionally, i do not know whether that would solve my issue either.
How can i format the return value of 'hasher.finalize()' to a hexadecimal string?
Full error log
error[E0277]: cannot add `<T as OutputSizeUser>::OutputSize` to `<T as OutputSizeUser>::OutputSize`
--> src/main.rs:80:28
|
80 | Ok(format!("{:x}", hash))
| ^^^^ no implementation for `<T as OutputSizeUser>::OutputSize <T as OutputSizeUser>::OutputSize`
|
= help: the trait `Add` is not implemented for `<T as OutputSizeUser>::OutputSize`
= note: required because of the requirements on the impl of `LowerHex` for `GenericArray<u8, <T as OutputSizeUser>::OutputSize>`
note: required by a bound in `ArgumentV1::<'a>::new_lower_hex`
= note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting the associated type
|
73 | fn calc_hash<T: Digest io::Write>(&self, file_path: String) -> Result<String, Box<dyn Error>> where <T as OutputSizeUser>::OutputSize: Add {
|
For more information about this error, try `rustc --explain E0277`.
error: could not compile `hash-cmp` due to previous error
I have tried to use the recommended solution with std::ops::Add
but did not manage to get it to work either.
Useful links
CodePudding user response:
After experimenting/reading for a while i found following solution:
fn calc_hash<T: Digest io::Write>(&self, file_path: String) -> Result<String, Box<dyn Error>> {
let mut hasher = T::new();
let mut file = fs::File::open(file_path)?;
io::copy(&mut file, &mut hasher)?;
let hash = hasher.finalize();
let mut hash_string = "".to_string();
for byte in hash.iter() {
hash_string = format!("{}{:02x}", hash_string, byte);
}
Ok(hash_string)
}
I'm basically just iterating over each byte of the GenericArray
and then concat it with the end result.