Rust 如何有条件地将类型分配给引用

Rust 如何有条件地将类型分配给引用,rust,Rust,今天下午我一直在玩Rust,并决定编写一个简单的哈希工具,可以完成所有主要的消化算法 我正在尝试这样做(意图应该是显而易见的): 在编译上述内容时,由于第一次匹配,它假定哈希程序的类型为Md5,当在“sha1”match分支中尝试分配sha1类型时失败。我打算在这个match语句中使用的所有类型都是traitDigest的实现者,所以我觉得应该有办法做到这一点 我试过: let mut hasher: Digest; 但这也没用。听起来你想用。您的示例大致如下所示: let mut hashe

今天下午我一直在玩Rust,并决定编写一个简单的哈希工具,可以完成所有主要的消化算法

我正在尝试这样做(意图应该是显而易见的):

在编译上述内容时,由于第一次匹配,它假定哈希程序的类型为
Md5
,当在
“sha1”
match分支中尝试分配
sha1
类型时失败。我打算在这个match语句中使用的所有类型都是trait
Digest
的实现者,所以我觉得应该有办法做到这一点

我试过:

let mut hasher: Digest;

但这也没用。

听起来你想用。您的示例大致如下所示:

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();
let mut hasher;
匹配alg{
“md5”=>{hasher=Box::new(md5::new())as Box}
“sha1”=>{hasher=Box::new(sha1::new())作为Box}
_=>{println!(“未实现算法”);
进程::退出(1);}
}
散列文件(&file\u name,&mut hasher).unwrap();
这只在某些条件下有效(例如,trait必须是),但我认为这是做你想做的事情的唯一方法。

此外,你还可以引用trait对象。这避免了堆分配:

trait Hasher { fn hash(&self) -> u8 { 42 } }

struct Md5;
struct Sha1;

impl Hasher for Md5 {}
impl Hasher for Sha1 {}

fn hash_it(which: &str) {
    let (md5, sha1);

    let hasher: &Hasher = match which {
        "md5" => {
            md5 = Md5;
            &md5
        },
        "sha1" => {
            sha1 = Sha1;
            &sha1
        },
        _ => unreachable!("Nope"),
    };

    hasher.hash();
}

fn main() {
    hash_it("md5");
    hash_it("sha1");
}

请注意,每个实现者都是在适当的匹配臂中创建的,因此您所做的工作不会超过需要。

感谢您的回复。我把它和盒子一起使用,我仍然不完全理解,但我稍后会仔细阅读。最终工作代码:

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();
}
fn进程\u散列(文件名:&str,alg:&str){
让有效的算法:Vec=
vec![“md5”、“sha1”、“SH224”、“SH256”、“SH384”、“SH512”、“SH512224”,
“sha512256”、“blake2b-64”、“ripemd160”、“漩涡”];
让mut-hasher:Box;
匹配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!(“未实现算法”);
println!(“有效选项:{}”,有效的_算法.join(“”);
进程::退出(1);}
}
散列文件(&file\u name,&mut*hasher).unwrap();
}

如果我在C或C++中看到了这个代码,我会立即拒绝它,因为引用一个潜在的未初始化的值充满了危险(下一个维护操作,它会被炸毁)。我看着它,只是点了点头。当你可以信任语言/编译器时,这真是太自由了。@MatthieuM。这不是真的吗!我总是很高兴地记住,在这种情况下,变量也不需要是
mut
。您可以通过将匹配结果分配给
hasher
(要点,因为注释没有足够的空间)来减少匹配的噪音。
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();
}