gpt4 book ai didi

generics - 计算散列(digest::Digest trait)并返回字符串的通用函数

转载 作者:行者123 更新时间:2023-12-03 11:24:31 31 4
gpt4 key购买 nike

我在解决这个问题时遇到了一些麻烦。我正在尝试编写一个通用函数,它可以接受任何 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::LowerHexformat!() 使用似乎需要 std::ops::AddOutputSizeGenericArray<u8, N> (即 N )由 .finalize() 返回.但是,非通用示例表明 ArrayLength<u8> 有这样的实现。 .
因此,鉴于我无法实现 std::ops::Add外部类型的特征,在这种情况下我如何满足编译器?
或者重新表述我的问题,尽管我 - 是 Rust 的新手 - 并不能 100% 确定这是我想要的:我如何告诉编译器处理 <D as sha2::Digest>::OutputSizeArrayLength<u8> ?
注意:我对 Rust 比较陌生,所以请记住这一点,并请引用适用于我的案例的确切文档,而不是一般的“文档”。我已经搜索了 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/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com