1use sha2::{Digest, Sha256};
4
5pub fn bytes(out: &mut Vec<u8>, value: &[u8]) {
7 out.extend_from_slice(
9 &u32::try_from(value.len())
10 .expect("framed field fits u32")
11 .to_be_bytes(),
12 );
13 out.extend_from_slice(value);
14}
15
16pub fn cce(label: &str, fields: &[&[u8]]) -> Vec<u8> {
18 let mut out = Vec::new();
19 bytes(&mut out, label.as_bytes());
20 for field in fields {
21 bytes(&mut out, field);
22 }
23 out
24}
25
26pub fn hash(value: &[u8]) -> [u8; 32] {
27 Sha256::digest(value).into()
28}
29
30#[cfg(test)]
31mod tests {
32 #[test]
33 fn canonical_fields_keep_their_length_prefixes() {
34 assert_eq!(
35 super::cce("x", &[b"yz", b""]),
36 vec![0, 0, 0, 1, b'x', 0, 0, 0, 2, b'y', b'z', 0, 0, 0, 0],
37 );
38 }
39}