当我使用板条箱创建 sha256 sum 时sha256,有一种旧的已弃用方法digest_bytes(有效),并且弃用还建议使用新digest函数。当我使用新函数作为替换时,会出现错误,编译器会建议一个非常奇怪但有效的解决方案。
fn main() {
let bytes: Vec<u8> = std::fs::read("./Cargo.toml").unwrap();
let hash: String = sha256::digest_bytes(&bytes); // deprecated but works
// let hash: String = sha256::digest(&bytes); // does not work
// let hash: String = sha256::digest(&*bytes); // works, but why
println!("{}", hash);
}
Run Code Online (Sandbox Code Playgroud)
sha256::digest(&bytes);这是我使用该行时的错误
--> src/main.rs:3:31
|
3 | let hash = sha256::digest(&bytes);
| -------------- ^^^^^^ the trait `Sha256Digest` is not implemented for `&Vec<u8>`
| |
| required by a bound introduced by this call
|
note: required by a bound in `sha256::digest`
--> /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/sha256-1.1.4/src/lib.rs:48:18
|
48 | pub fn digest<D: Sha256Digest>(input: D) -> String {
| ^^^^^^^^^^^^ required by this bound in `digest`
help: consider dereferencing here
|
3 | let hash = sha256::digest(&*bytes);
| +
Run Code Online (Sandbox Code Playgroud)
应用建议的解决方案&*就可以了,但我不明白为什么会这样。也许有人可以向我解释一下?
Vec可以取消引用A来获取切片。如果bytes有型Vec<u8>,则*bytes有型[u8],&*bytes还有型&[u8]。此行为是在Deref的实现中实现的Vec<_>。
该digest_byte()函数声明如下:
pub fn digest_bytes(input: &[u8]) -> String
Run Code Online (Sandbox Code Playgroud)
如果您将此函数调用为sha256::digest_bytes(&bytes),编译器会发现您传入了一个&Vec<u8>,而该函数需要一个&[u8]。根据Rust 的强制转换规则,在这种情况下,编译器将应用deref 强制转换&Vec<u8>,隐式转换为&[u8].
然而,该digest()函数是这样声明的:
pub fn digest<D: Sha256Digest>(input: D) -> String
Run Code Online (Sandbox Code Playgroud)
如果您调用digest(&bytes),编译器会再次看到您传入了&Vec<u8>,但编译器不知道您实际想要的目标类型。该声明只是指出您需要某种D实现Sha256Digest. 可能有许多类型实现该特征。编译器不会尝试应用任意强制来尝试最终得到实际上满足特征边界的类型(这样做将是一个非常糟糕的主意)。因此,对于此函数的通用版本,您必须手动取消bytes对 a 的引用&[u8],这是使用 完成的&*bytes。
两种调用之间的主要区别在于,在第一种情况下,编译器知道所需的类型是&[u8],而在第二种情况下,编译器只知道所需的类型是D需要编译器首先推断的类型。您还可以告诉编译器您想要什么D;sha256::digest::<&[u8]>(&bytes)也会起作用,因为您告诉编译器&bytes需要转换为&[u8].