Skip to content

Commit

Permalink
checksum: structure module
Browse files Browse the repository at this point in the history
  • Loading branch information
Johannes Wünsche committed Apr 12, 2024
1 parent 66d9984 commit 5672d8b
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 194 deletions.
1 change: 1 addition & 0 deletions betree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ lfu_cache = { git = "https://github.com/parcio/lfu-cache", rev = "haura-v5" }
rand = { version = "0.8", features = ["std_rng"] }

pmdk = { path = "./pmdk", optional = true }
rustc-hash = "1.1.0"

[dev-dependencies]
rand_xorshift = "0.3"
Expand Down
194 changes: 0 additions & 194 deletions betree/src/checksum.rs

This file was deleted.

67 changes: 67 additions & 0 deletions betree/src/checksum/fxhash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/// Impl for Checksum for FxHash.
use super::{Builder, Checksum, ChecksumError, State};
use crate::size::StaticSize;
use rustc_hash::FxHasher;
use serde::{Deserialize, Serialize};
use std::hash::Hasher;

/// The rustc own hash impl originally from Firefox.
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
pub struct FxHash(u64);

impl StaticSize for FxHash {
fn static_size() -> usize {
8
}
}

impl Checksum for FxHash {
type Builder = FxHashBuilder;

fn verify_buffer<I: IntoIterator<Item = T>, T: AsRef<[u8]>>(
&self,
data: I,
) -> Result<(), ChecksumError> {
let mut state = FxHashBuilder.build();
for x in data {
state.ingest(x.as_ref());
}
let other = state.finish();
if *self == other {
Ok(())
} else {
Err(ChecksumError)
}
}

fn builder() -> Self::Builder {
FxHashBuilder
}
}

/// The corresponding `Builder` for `FxHash`.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FxHashBuilder;

impl Builder<FxHash> for FxHashBuilder {
type State = FxHashState;

fn build(&self) -> Self::State {
FxHashState(FxHasher::default())
}
}

/// The internal state of `XxHash`.
pub struct FxHashState(FxHasher);

impl State for FxHashState {
type Checksum = FxHash;

fn ingest(&mut self, data: &[u8]) {
self.0.write(data);
}

fn finish(self) -> Self::Checksum {
FxHash(self.0.finish())
}
}
73 changes: 73 additions & 0 deletions betree/src/checksum/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! This module provides a `Checksum` trait for verifying data integrity.
use crate::size::Size;
use serde::{de::DeserializeOwned, Serialize};
use std::{error::Error, fmt, iter::once};

mod fxhash;
mod xxhash;

pub use fxhash::{FxHash, FxHashBuilder};
pub use xxhash::{XxHash, XxHashBuilder};

/// A checksum to verify data integrity.
pub trait Checksum:
Serialize + DeserializeOwned + Size + Clone + Send + Sync + fmt::Debug + 'static
{
/// Builds a new `Checksum`.
type Builder: Builder<Self>;

/// Verifies the contents of the given buffer which consists of multiple
/// `u8` slices.
fn verify_buffer<I: IntoIterator<Item = T>, T: AsRef<[u8]>>(
&self,
data: I,
) -> Result<(), ChecksumError>;

/// Verifies the contents of the given buffer.
fn verify(&self, data: &[u8]) -> Result<(), ChecksumError> {
self.verify_buffer(once(data))
}

/// Create a valid empty builder for this checksum type.
fn builder() -> Self::Builder;
}

/// A checksum builder
pub trait Builder<C: Checksum>:
Serialize + DeserializeOwned + Clone + Send + Sync + fmt::Debug + 'static
{
/// The internal state of the checksum.
type State: State<Checksum = C>;

/// Create a new state to build a checksum.
fn build(&self) -> Self::State;
}

/// Holds a state for building a new `Checksum`.
pub trait State {
/// The resulting `Checksum`.
type Checksum: Checksum;

/// Ingests the given data into the state.
fn ingest(&mut self, data: &[u8]);

/// Builds the actual `Checksum`.
fn finish(self) -> Self::Checksum;
}

/// This is the error that will be returned when a `Checksum` does not match.
#[derive(Debug)]
pub struct ChecksumError;

impl fmt::Display for ChecksumError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Failed to verify the integrity")
}
}

impl Error for ChecksumError {
fn description(&self) -> &str {
"a checksum error occurred"
}
}
Loading

0 comments on commit 5672d8b

Please sign in to comment.