我想在 Rust 中设计一个结构,它可以用实现Digest
特征的对象构造,并抽象方法背后的哈希行为。这是一个无法编译的简单示例:
use digest::Digest;
struct Crypto<D: Digest> {
digest: D,
}
impl<D> Crypto<D>
where
D: Digest,
{
pub fn hash(&self, data: &[u8]) -> Vec<u8> {
self.digest.chain(&data).finalize_reset().to_vec()
}
}
这无法编译,因为self
在方法签名中不可变地借用,所以self.digest
不能不可变地借用。因此,它尝试复制它,但是由于D
没有将泛型定义为遵循该Copy
特征,因此它失败了。
无论如何,我宁愿不复制它。我宁愿有一个实例。我尝试过的一些事情:
更改要采用的方法签名
mut self
。但这会将对象的所有权转移到方法中,之后就不能再使用它了。digest
将字段包装在RefMut
orCell
中,以采用内部可变性,但我无法找出正确的方法来借用可digest
变性而不尝试复制值。此外,如果可能,希望在编译时保留借用检查。将 of 的类型更改为
D
返回 a 实例的函数Digest
,并使用它在方法内实例化一个新的摘要hash()
。但是,即使我将其定义为D: Box<dyn Digest>
,编译器也会抱怨the value of the associated type OutputSize (from trait digest::Digest) must be specified
. 所以这看起来很有挑战性,因为我想支持不同的哈希算法,这些算法会产生不同大小的哈希值。
我试图使用泛型来获得 trait bound 的编译时优势,但不得不承认,在与行为需要可变性的对象组合时,内部可变性的挑战阻碍了我。非常感谢指向这个设计挑战的惯用 Rust 解决方案的指针。
奖励 - 我如何避免to_vec()
复制并只返回由返回的数组finalize_reset()
?