Is there any way to make this code work without using Box
ing:
fn some_func(my_type: MyType, some_str: &str) -> bool {
let mut hmac = match my_type {
MyType::MyType1 => create_hmac(Sha256::new(), some_str),
MyType::MyType2 => create_hmac(Sha384::new(), some_str),
MyType::MyType3 => create_hmac(Sha512::new(), some_str),
_ => panic!()
};
//some calculations goes HERE, NOT in create_hmac function...
hmac.input("fdsfdsfdsfd".to_string().as_bytes());
//something else....
true
}
fn create_hmac<D: Digest>(digest: D, some_str: &str) -> Hmac<D> {
Hmac::new(digest, some_str.to_string().as_bytes())
}
The library it's using is https://github.com/DaGenix/rust-crypto
You need to either Box or use a reference, as a "trait object" can only work behind a pointer.
Here's a very simplified version of your code. You have three different structs that implement the same trait (Digest)
Note that in the real case, not only all ShaXXX types are different for the type system, they have a different memory layout as well (compare Engine256State with Engine512State for instance), so this rules out unsafe tricks with transmute.
So, as said, you can use Box or references (but you have to pre-create a concrete instance before the match if you want to use references):
Note that a
Box
is doing the equivalent of what most Garbage Collected languages do for you under the hood when you want to only use an object through its interface. Some memory is dynamically allocated for the concrete objects, but you're only really allowed to pass around a pointer to the memory.In your case (but I haven't tested the code below) you should be able to do:
and use it as:
One addition and one clarification to Paolo's good answer. First, you could make your enum incorporate the appropriate
Sha*
struct and then implementDigest
by delegating it as appropriate. This might not make sense in all cases, but if conceptually that's what you are doing this might make sense:Also, you don't have to actually instantiate all of the types if you want to use references, you just have to ensure that the one you use is available. You also have to have places where the reference can live beyond the
match
expression: