'Match and do the same function block except for a type
I need to do the same operations as in Some(Md5Sess), changing only the type that calls digest. So change from <md5::Md5>::digest to <sha2::Sha256>::digest etc and possibly many others:
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))),
}
My only idea is to create a function that is generic on the type of the hash, with the inconvenient of having lots of arguments, for each variable used in that block.
Is there a better way to solve this problem?
I tried with macros too, only to remember that in Rust, macros are not like in C where they don't care about the text being used. I did a macro that matched by the type of the hash like my_macro!(md5::Md5) but then it complained about the variables being used in the block.
Solution 1:[1]
Disclaimer: I do not claim this is the best solution, as I would probably prefer using a function if at all possible, but if that is out of the question, here goes:
The duplicate can help you reuse your block in all the match cases:
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
},
...
}
}
This will repeat the function body (which has been out of the its original block and into a substitution) in each match case, replacing hash_type with the hash type you provide in func([md5::Md5]), func([sha2::Sha256]), etc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
