我正在尝试使用 AES 板条箱,它提供三种算法:AES128、AES192 和 AES256。我正在尝试创建一个结构,该结构可以通过检测密钥大小来创建正确的算法,并将其保存以供以后使用。
我看到它们都实现了 BlockEncrypt (我只需要加密)特征,但是当我尝试在结构中创建具有这种类型的字段时,即使提供大小,我也会得到“该特征BlockEncrypt无法制成对象。”特征不能被制作成对象,因为它需要Self: Sized“错误。
pub struct MyStruct<'a, T: Sized> {
ciph: Box< dyn BlockEncrypt<BlockSize = T>>,
}
Run Code Online (Sandbox Code Playgroud)
作为超类型的特征Sized不是“对象安全”的,这意味着动态调度使用dyn在这些类型的特征上是不可能的。
您可以相对简洁地完成此操作,方法是对要处理的每种可能类型使用枚举,并结合一个宏,该宏将整齐地生成match动态分派每种枚举可能性所需的所有臂。
为了使这个解释变得简单,我将定义一个新的特征(使用超Sized类型),以便这个答案不依赖于特定的板条箱:
trait SampleTrait: Sized {
fn method_a(&self, foo: &str);
fn method_b(&self, foo: i32, bar: String) -> String;
}
Run Code Online (Sandbox Code Playgroud)
现在我们至少需要此特征的两个实现来演示解决方案:
struct ImplA;
struct ImplB;
impl SampleTrait for ImplA {
fn method_a(&self, foo: &str) {
println!("<ImplA as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplA as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplA: {}", bar)
}
}
impl SampleTrait for ImplB {
fn method_a(&self, foo: &str) {
println!("<ImplB as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplB as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplB: {}", bar)
}
}
Run Code Online (Sandbox Code Playgroud)
枚举只需要最少化您需要处理的每种可能的类型:
enum DynSampleTrait {
ImplA(ImplA),
ImplB(ImplB),
}
Run Code Online (Sandbox Code Playgroud)
现在要对此进行调度,您必须执行以下操作:
match value {
DynSampleTrait::ImplA(v) => v.method_a("something"),
DynSampleTrait::ImplB(v) => v.method_a("something"),
}
Run Code Online (Sandbox Code Playgroud)
为了避免重复,让我们声明一个宏来match为我们生成整个内容:
macro_rules! dyn_sample_trait_call {
(($m:expr) $v:ident => $code:block) => {
match $m {
DynSampleTrait::ImplA($v) => $code,
DynSampleTrait::ImplB($v) => $code,
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以像这样使用宏:
dyn_sample_trait_call!((value) v => { v.method_a("something") })
Run Code Online (Sandbox Code Playgroud)
value进入匹配表达式,并且v是解包枚举可能性所持有的内部值的标识符。它们是分开的,以便您可以匹配引用,如果您不想使用拥有的DynSampleTrait:
dyn_sample_trait_call!((&value) v => { v.method_a("something") })
Run Code Online (Sandbox Code Playgroud)
(游乐场)
| 归档时间: |
|
| 查看次数: |
741 次 |
| 最近记录: |