我今天下午一直在玩Rust,并决定编写一个简单的哈希工具,可以做所有主要的消化算法。
我正在尝试做这样的事情(意图应该很明显):
let mut hasher;
match alg {
"md5" => { hasher = Md5::new() }
"sha1" => { hasher = Sha1::new() }
_ => { println!("Algorithm not implemented");
process::exit(1); }
}
hash_file(&file_name, &mut hasher).unwrap();
在编译上述内容时,由于第一次匹配,它假定hasher属于Md5
类型并且在"sha1"
匹配分支中失败时,它会尝试分配Sha1
类型。我打算在这个匹配语句中使用的所有类型都是特征Digest
的实现者,所以我觉得应该有办法做到这一点。
我试过了:
let mut hasher: Digest;
但这也不起作用。
答案 0 :(得分:7)
除了creating a boxed trait object之外,您还可以引用特征对象。这避免了堆分配:
"</item>"
请注意,每个实现者只能在相应的匹配臂中创建,因此您的工作量不会超出您的需要。
答案 1 :(得分:6)
听起来你想使用trait objects。那么你的例子看起来大致如下:
let mut hasher;
match alg {
"md5" => { hasher = Box::new(Md5::new()) as Box<Digest>}
"sha1" => { hasher = Box::new(Sha1::new()) as Box<Digest>}
_ => { println!("Algorithm not implemented");
process::exit(1); }
}
hash_file(&file_name, &mut hasher).unwrap();
这只能在某些条件下工作(例如,特性必须是object safe),但我认为这是你想要的唯一方法。
答案 2 :(得分:0)
感谢您的回复。我得到它与Box工作,我仍然不完全理解,但我将在稍后阅读。最终工作代码:
fn process_hash(file_name: &str, alg: &str) {
let valid_algorithms: Vec<&str> =
vec!["md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha512224",
"sha512256", "blake2b-64", "ripemd160", "whirlpool"];
let mut hasher: Box<Digest>;
match alg {
"md5" => { hasher = Box::new(Md5::new()) }
"sha1" => { hasher = Box::new(Sha1::new()) }
"sha224" => { hasher = Box::new(Sha224::new()) }
"sha256" => { hasher = Box::new(Sha256::new()) }
"sha384" => { hasher = Box::new(Sha384::new()) }
"sha512" => { hasher = Box::new(Sha512::new()) }
"sha512224" => { hasher = Box::new(Sha512Trunc224::new()) }
"sha512256" => { hasher = Box::new(Sha512Trunc256::new()) }
"blake2b-64" => { hasher = Box::new(Blake2b::new(64)) }
"ripemd160" => { hasher = Box::new(Ripemd160::new()) }
"whirlpool" => { hasher = Box::new(Whirlpool::new()) }
_ => { println!("Algorithm not implemented");
println!("Valid choices: {}", valid_algorithms.join(" "));
process::exit(1); }
}
hash_file(&file_name, &mut *hasher).unwrap();
}