mirror of
https://github.com/BLAKE3-team/BLAKE3
synced 2024-09-22 00:55:28 +02:00
9f509a8f1f
For the Read and Write traits, this also allows the compiler to see that the return value is always Ok, allowing it to remove the Err case from the caller as dead code.
96 lines
2.5 KiB
Rust
96 lines
2.5 KiB
Rust
// This module is for incremental use cases like the `bao` crate, which need to
|
|
// get their hands on internal chunk and parent chaining values. The vast
|
|
// majority of users should ignore this and use the publicly documented
|
|
// interface instead.
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct ChunkState(crate::ChunkState);
|
|
|
|
impl ChunkState {
|
|
// Currently this type only supports the regular hash mode. If an
|
|
// incremental user needs keyed_hash or derive_key, we can add that.
|
|
pub fn new(chunk_counter: u64) -> Self {
|
|
Self(crate::ChunkState::new(
|
|
crate::IV,
|
|
chunk_counter,
|
|
0,
|
|
crate::platform::Platform::detect(),
|
|
))
|
|
}
|
|
|
|
#[inline]
|
|
pub fn len(&self) -> usize {
|
|
self.0.len()
|
|
}
|
|
|
|
#[inline]
|
|
pub fn update(&mut self, input: &[u8]) -> &mut Self {
|
|
self.0.update(input);
|
|
self
|
|
}
|
|
|
|
pub fn finalize(&self, is_root: bool) -> crate::Hash {
|
|
let output = self.0.output();
|
|
if is_root {
|
|
output.root_hash()
|
|
} else {
|
|
output.chaining_value().into()
|
|
}
|
|
}
|
|
}
|
|
|
|
// As above, this currently assumes the regular hash mode. If an incremental
|
|
// user needs keyed_hash or derive_key, we can add that.
|
|
pub fn parent_cv(
|
|
left_child: &crate::Hash,
|
|
right_child: &crate::Hash,
|
|
is_root: bool,
|
|
) -> crate::Hash {
|
|
let output = crate::parent_node_output(
|
|
left_child.as_bytes(),
|
|
right_child.as_bytes(),
|
|
crate::IV,
|
|
0,
|
|
crate::platform::Platform::detect(),
|
|
);
|
|
if is_root {
|
|
output.root_hash()
|
|
} else {
|
|
output.chaining_value().into()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_chunk() {
|
|
assert_eq!(
|
|
crate::hash(b"foo"),
|
|
ChunkState::new(0).update(b"foo").finalize(true)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parents() {
|
|
let mut hasher = crate::Hasher::new();
|
|
let mut buf = [0; crate::CHUNK_LEN];
|
|
|
|
buf[0] = 'a' as u8;
|
|
hasher.update(&buf);
|
|
let chunk0_cv = ChunkState::new(0).update(&buf).finalize(false);
|
|
|
|
buf[0] = 'b' as u8;
|
|
hasher.update(&buf);
|
|
let chunk1_cv = ChunkState::new(1).update(&buf).finalize(false);
|
|
|
|
hasher.update(b"c");
|
|
let chunk2_cv = ChunkState::new(2).update(b"c").finalize(false);
|
|
|
|
let parent = parent_cv(&chunk0_cv, &chunk1_cv, false);
|
|
let root = parent_cv(&parent, &chunk2_cv, true);
|
|
assert_eq!(hasher.finalize(), root);
|
|
}
|
|
}
|