作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在解决这个问题时遇到了一些麻烦。我正在尝试编写一个通用函数,它可以接受任何 digest::Digest
并吐出计算摘要的字符串形式(“十六进制字符串”)。
这是the non-generic version作为最小的例子:
#![forbid(unsafe_code)]
#![forbid(warnings)]
extern crate sha2; // 0.9.1
use sha2::{Sha256, Digest}; // 0.9.1
fn main() {
let hash = Sha256::new().chain("String data").finalize();
let s = format!("{:x}", hash);
println!("Result: {}", s);
}
...这是我的尝试
at a generic version :
#![forbid(unsafe_code)]
#![forbid(warnings)]
extern crate sha2; // 0.9.1
extern crate digest; // 0.9.0
use digest::Digest;
use sha2::Sha256;
fn compute_hash<D: Digest>(input_data: &str) -> String {
let mut hasher = D::new();
hasher.update(input_data.as_bytes());
let digest = hasher.finalize();
format!("{:x}", digest)
}
fn main() {
let s = compute_hash::<Sha256>("String data");
println!("Result: {}", s);
}
...这给出了以下错误:
Compiling playground v0.0.1 (/playground)
error[E0277]: cannot add `<D as sha2::Digest>::OutputSize` to `<D as sha2::Digest>::OutputSize`
--> src/lib.rs:13:21
|
13 | format!("{:x}", digest)
| ^^^^^^ no implementation for `<D as sha2::Digest>::OutputSize + <D as sha2::Digest>::OutputSize`
|
= help: the trait `std::ops::Add` is not implemented for `<D as sha2::Digest>::OutputSize`
= note: required because of the requirements on the impl of `std::fmt::LowerHex` for `digest::generic_array::GenericArray<u8, <D as sha2::Digest>::OutputSize>`
= note: required by `std::fmt::LowerHex::fmt`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting the associated type
|
9 | fn compute_hash<D: Digest>(input_data: &str) -> String where <D as sha2::Digest>::OutputSize: std::ops::Add {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`.
现在假设我正确理解错误,执行
std::fmt::LowerHex
由
format!()
使用似乎需要
std::ops::Add
为
OutputSize
的
GenericArray<u8, N>
(即
N
)由
.finalize()
返回.但是,非通用示例表明
ArrayLength<u8>
有这样的实现。 .
std::ops::Add
外部类型的特征,在这种情况下我如何满足编译器?
<D as sha2::Digest>::OutputSize
同
ArrayLength<u8>
?
digest
的文档,适用于
digest::Digest
的各种实现者,对于这个错误和(我认为是)类似的问题和 Rust Book(2018 版)中的特征主题,在我问之前将近三个小时。谢谢。
use digest::Digest;
.那是因为将来应该遵循其他哈希算法,并且使用
digest::Digest
似乎更有意义。直接代替重新导出的
Digest
来自其中一位实现者。如果有反对的理由,请随时发表评论。
最佳答案
Rust 要求您指定在泛型中使用的所有功能。那个笔记:
| ^^^^^^ no implementation for `<D as sha2::Digest>::OutputSize + <D as sha2::Digest>::OutputSize`
= help: the trait `std::ops::Add` is not implemented for `<D as sha2::Digest>::OutputSize`
试图说我们正在使用
Add
在类型
D::OutputSize
但不需要它作为约束,我们可以这样做:
fn compute_hash<D: Digest>(input_data: &str) -> String
where D::OutputSize: std::ops::Add
如果您进行此更改,您将遇到下一个错误:
| ^^^^^^ the trait `digest::generic_array::ArrayLength<u8>` is not implemented for `<<D as sha2::Digest>::OutputSize as std::ops::Add>::Output`
所以还有另一个要求,但我们也可以添加:
fn compute_hash<D: Digest>(input_data: &str) -> String
where D::OutputSize: std::ops::Add,
<D::OutputSize as std::ops::Add>::Output: digest::generic_array::ArrayLength<u8>
这将编译。
finalize
返回
Output<D>
我们知道它是类型
GenericArray<u8, <D as Digest>::OutputSize>
.显然
format!("{:x}", ...)
需要特性
LowerHex
所以我们可以看到这个类型什么时候满足这个特征。
See :
impl<T: ArrayLength<u8>> LowerHex for GenericArray<u8, T>
where
T: Add<T>,
<T as Add<T>>::Output: ArrayLength<u8>,
那看起来很熟悉。所以返回类型为
finalize
是满足
LowerHex
如果这些限制是真的。
LowerHex
进行格式化和
we can say that :
fn compute_hash<D: Digest>(input_data: &str) -> String
where digest::Output<D>: core::fmt::LowerHex
由于这可以直接表达我们在泛型函数中使用的内容,因此这似乎更可取。
关于generics - 计算散列(digest::Digest trait)并返回字符串的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64326373/
我是一名优秀的程序员,十分优秀!