匹配并执行除类型之外的相同功能块



我需要执行与Some(Md5Sess)中相同的操作,只更改调用digest的类型。因此,从<md5::Md5>::digest更改为<sha2::Sha256>::digest等,可能还有许多其他更改:

match challenge.algorithm {
Some(Md5Sess) => {
//I need to repeat this entire block, only changing the `md5::Md5` 
//by the correct hashing function
let a1_part1 =
<md5::Md5>::digest(format!("{}:{}:{}", username, realm, password).as_bytes());
let cnonce = match cnonce {
Some(cnonce) => cnonce,
None => return Err(DigestError::MissingCNonce),
};
let a1_part2 = format!("{}:{}", nonce, cnonce);
a1 = format!("{:x}:{}", a1_part1, a1_part2);
let entity_body = match &body {
Some(body) => body.as_ref(),
None => "".as_bytes(),
};
hash_common::<md5::Md5>(
method,
chosen_qop,
a1,
nonce,
Some(cnonce),
nonce_count,
uri,
body,
)
}
Some(Sha512Trunc256Sess) => 
Err(DigestError::DigestAlgorithmNotImplemented(Sha512Trunc256Sess)),
Some(Sha256Sess) => 
Err(DigestError::DigestAlgorithmNotImplemented(Sha256Sess)),
Some(Algorithm::Other(s)) => 
Err(DigestError::DigestAlgorithmNotImplemented(Algorithm::Other(s))),
}

我唯一的想法是为该块中使用的每个变量创建一个对哈希类型通用的函数,这样不方便有很多参数。

有更好的方法来解决这个问题吗?

我也尝试过使用宏,只记得在Rust中,宏不像C中那样不关心使用的文本。我做了一个宏,它和散列的类型匹配,比如my_macro!(md5::md5(,但随后它抱怨块中使用的变量。

您可以先选择要应用的函数,然后操作数据:

// Select the functions to apply
let (digest, common) = match challenge.algorithm {
Some (Md5Sess) => (<md5::Md5>::digest, hash_common::<md5::Md5>),
Some (Sha256Sess) => (<sha2::Sha256>::digest, hash_common::<sha2::Sha256>),
_ => todo!(),
}
// Now process the data
let a1_part1 = digest (format!("{}:{}:{}", username, realm, password).as_bytes());
let cnonce = match cnonce {
Some(cnonce) => cnonce,
None => return Err (DigestError::MissingCNonce)
};
let a1_part2 = format!("{}:{}", nonce, cnonce);
a1 = format!("{:x}:{}", a1_part1, a1_part2);
let entity_body = match &body {
Some (body) => body.as_ref(),
None => "".as_bytes()
};
common (method, chosen_qop, a1, nonce, Some (cnonce), nonce_count, uri, body)

免责声明:我并不声称这是最好的解决方案,因为如果可能的话,我可能更喜欢使用函数,但如果这是不可能的,这里是:

重复可以帮助您在所有匹配情况下重用您的块:

use duplicate::duplicate:
duplicate! {
[
func(hash_type);
[
//I need to repeat this entire block, only changing the `md5::Md5` by the correct hashing function
let a1_part1 = <hash_type>::digest(format!("{}:{}:{}", username, realm, password).as_bytes());
let cnonce = match cnonce {
Some(cnonce) => cnonce,
None => return Err(DigestError::MissingCNonce)
};
let a1_part2 = format!("{}:{}", nonce, cnonce);
a1 = format!("{:x}:{}", a1_part1, a1_part2);
let entity_body = match &body {
Some(body) => body.as_ref(),
None => "".as_bytes()
};
hash_common::<hash_type>(method, chosen_qop, a1, nonce, Some(cnonce), nonce_count, uri, body)
];
]
match challenge.algorithm {
Some(Md5Sess) => {
func([md5::Md5]) // Duplicates the block with hash_type = md5::Md5
},
Some(Sha512Trunc256Sess) => {
func([sha2::Sha256])// Duplicates the block with hash_type = sha2::Sha256
},
...
}
}

这将在每个匹配的情况下重复函数体(它已经脱离了原来的块并进入了替换(,将hash_type替换为您在func([md5::Md5])func([sha2::Sha256])等中提供的哈希类型。

最新更新