use serde_json::Value;
use sha2::{Digest, Sha256};
use crate::canonical::write_canonical;
use crate::opts::HashOpts;
pub fn hash_canonical(v: &Value) -> [u8; 32] {
hash_canonical_with(v, &HashOpts::default())
}
pub fn hash_canonical_with(v: &Value, opts: &HashOpts) -> [u8; 32] {
let mut hasher = Sha256Writer(Sha256::new());
write_canonical(&mut hasher, v, opts).expect("Sha256 writer is infallible");
hasher.0.finalize().into()
}
pub fn hash_canonical_hex(v: &Value) -> String {
hex_lower(&hash_canonical(v))
}
pub fn hash_canonical_hex_with(v: &Value, opts: &HashOpts) -> String {
hex_lower(&hash_canonical_with(v, opts))
}
fn hex_lower(bytes: &[u8]) -> String {
let mut s = String::with_capacity(bytes.len() * 2);
for b in bytes {
s.push(char_for_nibble(b >> 4));
s.push(char_for_nibble(b & 0xf));
}
s
}
fn char_for_nibble(n: u8) -> char {
match n {
0..=9 => (b'0' + n) as char,
_ => (b'a' + n - 10) as char,
}
}
struct Sha256Writer(Sha256);
impl std::io::Write for Sha256Writer {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.update(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}