use sha2::{Digest, Sha256};
pub fn hex(bytes: &[u8]) -> String {
let mut hex = String::new();
for byte in bytes.iter() {
hex.push_str(&format!("{:02x}", byte));
}
hex
}
pub fn from_hex(hex: &str) -> Option<Vec<u8>> {
if hex.len() % 2 != 0 {
return None;
}
(0..hex.len())
.step_by(2)
.map(|i| match u8::from_str_radix(&hex[i..i + 2], 16) {
Ok(byte) => Some(byte),
Err(_) => None,
})
.collect()
}
pub fn quorum(n: u32) -> Option<u32> {
let f = (n - 1) / 3;
if f == 0 {
return None;
}
Some((2 * f) + 1)
}
pub fn hash(bytes: &[u8]) -> Vec<u8> {
let mut hasher = Sha256::new();
hasher.update(bytes);
hasher.finalize().to_vec()
}
pub fn union(a: &[u8], b: &[u8]) -> Vec<u8> {
let mut union = Vec::with_capacity(a.len() + b.len());
union.extend_from_slice(a);
union.extend_from_slice(b);
union
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hex() {
let b = &[];
let h = hex(b);
assert_eq!(h, "");
assert_eq!(from_hex(&h).unwrap(), b.to_vec());
let b = &[0x01];
let h = hex(b);
assert_eq!(h, "01");
assert_eq!(from_hex(&h).unwrap(), b.to_vec());
let b = &[0x01, 0x02, 0x03];
let h = hex(b);
assert_eq!(h, "010203");
assert_eq!(from_hex(&h).unwrap(), b.to_vec());
let h = "0102030";
assert!(from_hex(h).is_none());
let h = "01g3";
assert!(from_hex(h).is_none());
}
#[test]
fn test_quorum() {
assert_eq!(quorum(3), None);
assert_eq!(quorum(4), Some(3));
assert_eq!(quorum(7), Some(5));
assert_eq!(quorum(10), Some(7));
}
#[test]
fn test_hash() {
let empty = hash(b"");
assert_eq!(
hex(&empty),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
);
let single = hash(b"a");
assert_eq!(
hex(&single),
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
);
let multiple = hash(b"hello world");
assert_eq!(
hex(&multiple),
"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
);
}
#[test]
fn test_union() {
assert_eq!(union(&[], &[]), []);
assert_eq!(union(&[], &[0x01, 0x02, 0x03]), [0x01, 0x02, 0x03]);
assert_eq!(
union(&[0x01, 0x02, 0x03], &[0x04, 0x05, 0x06]),
[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
);
}
}