Skip to content

Commit

Permalink
Merge pull request #2 from Terseus/doc
Browse files Browse the repository at this point in the history
Doc
  • Loading branch information
Terseus authored Dec 16, 2023
2 parents f8ebbe5 + 9796e8e commit afbe424
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
name = "libmd5"
name = "ya_md5"
path = "src/lib.rs"

[dependencies]
Expand Down
13 changes: 8 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,26 @@ endif


# Builds the project
.PHONY: build
build:
build: test
cargo build $(BUILD_FLAGS)

# Run the tests
.PHONY: test
test:
cargo test $(TEST_FLAGS) -- $(TEST_BIN_FLAGS)

# Clean all artifacts
.PHONY: clean
clean:
cargo clean

# Generates the doc
doc: test
cargo doc --no-deps

# Prints Makefile variables - for debugging
.PHONY: debug
debug:
@echo "BUILD_FLAGS=$(BUILD_FLAGS)"
@echo "TEST_FLAGS=$(TEST_FLAGS)"
@echo "TEST_BIN_FLAGS=$(TEST_BIN_FLAGS)"


.PHONY: build test clean debug doc
1 change: 1 addition & 0 deletions src/hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::Display;

/// The hash computed by the [Md5Hasher](crate::Md5Hasher).
#[derive(Debug)]
pub struct Hash {
value: [u8; 16],
Expand Down
86 changes: 86 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
#![warn(missing_docs)]

//! An implementation of the [MD5] hash algorithm capable to hash data readed from a
//! [std::io::Read] implementation.
//!
//! ## Example
//! ```rust
//! use std::fs::File;
//! use std::io::prelude::*;
//! use ya_md5::Md5Hasher;
//! use ya_md5::Hash;
//! use ya_md5::Md5Error;
//!
//! fn main() -> Result<(), Md5Error> {
//! std::fs::write("foo.txt", b"hello world")?;
//! let hash = {
//! let mut file = File::open("foo.txt")?;
//! Md5Hasher::hash(&mut file)?
//! };
//! std::fs::remove_file("foo.txt")?;
//! let result = format!("{}", hash);
//! assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
//! Ok(())
//! }
//! ```
//!
//! [MD5]: https://en.wikipedia.org/wiki/MD5

mod chunk;
mod chunk_provider;
mod conversions;
Expand All @@ -16,6 +44,12 @@ use crate::hash_compute_state::HashComputeState;
use std::io::Cursor;
use std::io::Read;

/// A hasher thath computes the MD5 hash of a given list of chunks.
///
/// Each chunk is defined as a buffer of type `[u8; 64]`.
///
/// Provides conveniente functions to compute the MD5 hash of various sources without having to
/// create and manage an instance.
pub struct Md5Hasher {
state: HashComputeState,
}
Expand All @@ -27,12 +61,30 @@ impl Default for Md5Hasher {
}

impl Md5Hasher {
/// Creates an instance with the initial internal state.
pub fn new() -> Self {
Md5Hasher {
state: HashComputeState::new_initial(),
}
}

/// Computes and returns the hash of the data that can be readed from the `input`.
///
/// # Errors
///
/// If there's any I/O error while reading the `input` an error is returned.
///
/// # Examples
///
/// ```
/// use std::io::Cursor;
/// use ya_md5::Md5Hasher;
///
/// let hash = Md5Hasher::hash(&mut Cursor::new("hello world".as_bytes()))
/// .expect("Unexpected error reading from a cursor");
/// let result = format!("{}", hash);
/// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
/// ```
pub fn hash(input: &mut dyn Read) -> Result<Hash, Md5Error> {
let mut chunk_provider = ChunkProvider::new(input);
let mut hasher = Md5Hasher::new();
Expand All @@ -43,22 +95,56 @@ impl Md5Hasher {
Ok(hasher.compute())
}

/// Computes and returns the hash of the data in the `Vec`.
///
/// # Examples
///
/// ```
/// use ya_md5::Md5Hasher;
///
/// let hash = Md5Hasher::hash_vec(&Vec::from("hello world".as_bytes()));
/// let result = format!("{}", hash);
/// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
/// ```
pub fn hash_vec(data: &Vec<u8>) -> Hash {
Self::unsafe_hash(&mut Cursor::new(data))
}

/// Computes and returns the hash of the data in the slice.
///
/// # Examples
/// ```
/// use ya_md5::Md5Hasher;
///
/// let hash = Md5Hasher::hash_slice("hello world".as_bytes());
/// let result = format!("{}", hash);
/// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
/// ```
pub fn hash_slice(data: &[u8]) -> Hash {
Self::unsafe_hash(&mut Cursor::new(data))
}

/// Computes and returns the hash of the data in the string slice.
///
/// # Examples
/// ```
/// use ya_md5::Md5Hasher;
///
/// let hash = Md5Hasher::hash_str("hello world");
/// let result = format!("{}", hash);
/// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
/// ```
pub fn hash_str(data: &str) -> Hash {
Self::unsafe_hash(&mut Cursor::new(data.as_bytes()))
}

/// Process a single chunk and use it to compute the internal state.
pub fn add_chunk(&mut self, chunk: RawChunk) {
self.add_chunk_direct(Chunk::from(chunk))
}

/// Computes the hash of the internal state of the instance, consuming the instance in the
/// process.
pub fn compute(self) -> Hash {
Hash::from(self.state.to_raw())
}
Expand Down
25 changes: 25 additions & 0 deletions src/md5_error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
use thiserror::Error;

/// The error of a [Md5Hasher](crate::Md5Hasher) operation.
#[derive(Error, Debug)]
pub enum Md5Error {
/// Error while doing [read](std::io::Read::read) from an input.
#[error("Error reading input: {0}")]
ReadError(std::io::Error),
/// Other I/O errors.
/// While the [Md5Hasher](crate::Md5Hasher) don't use this error, it allows to create ergonomic
/// functions for hashing a [std::io::Read] object.
/// ```
/// use std::fs::File;
/// use std::io::prelude::*;
/// use ya_md5::Md5Hasher;
/// use ya_md5::Hash;
/// use ya_md5::Md5Error;
///
/// fn hash_file() -> Result<Hash, Md5Error> {
/// std::fs::write("foo.txt", b"hello world")?;
/// let hash = {
/// let mut file = File::open("foo.txt")?;
/// Md5Hasher::hash(&mut file)?
/// };
/// std::fs::remove_file("foo.txt")?;
/// Ok(hash)
/// }
///
/// ```
#[error("Unexpected I/O error: {0}")]
IOError(#[from] std::io::Error),
}
15 changes: 3 additions & 12 deletions tests/test_md5_hasher.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
use libmd5::Md5Error;
use libmd5::Md5Hasher;
use log::LevelFilter;
use rstest::rstest;
use simplelog::{ColorChoice, Config, TermLogger, TerminalMode};
use std::io;
use std::io::Seek;
use std::io::Write;
use tempfile::tempfile;
use thiserror::Error;

#[derive(Error, Debug)]
enum TestError {
#[error("Md5Error: {0}")]
Md5Error(#[from] Md5Error),
#[error("I/O Error: {0}")]
IOError(#[from] io::Error),
}
use ya_md5::Md5Error;
use ya_md5::Md5Hasher;

#[allow(unused)]
fn setup_logger() {
Expand Down Expand Up @@ -89,7 +80,7 @@ fn test_hash_str(#[case] data: &str, #[case] expected: &str) {
}

#[rstest]
fn test_hash_input() -> Result<(), TestError> {
fn test_hash_input() -> Result<(), Md5Error> {
let mut file = tempfile()?;
write!(file, "abc")?;
file.seek(io::SeekFrom::Start(0))?;
Expand Down

0 comments on commit afbe424

Please sign in to comment.