ya_md5/
lib.rs

1#![warn(missing_docs)]
2
3//! An implementation of the [MD5] hash algorithm capable to hash data readed from a
4//! [std::io::Read] implementation.
5//!
6//! ## Example
7//! ```rust
8//! use std::fs::File;
9//! use std::io::prelude::*;
10//! use ya_md5::Md5Hasher;
11//! use ya_md5::Hash;
12//! use ya_md5::Md5Error;
13//!
14//! fn example() -> Result<(), Md5Error> {
15//!     std::fs::write("foo.txt", b"hello world")?;
16//!     let hash = {
17//!         let mut file = File::open("foo.txt")?;
18//!         Md5Hasher::hash(&mut file)?
19//!     };
20//!     std::fs::remove_file("foo.txt")?;
21//!     let result = format!("{}", hash);
22//!     assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
23//!     Ok(())
24//! }
25//! ```
26//!
27//! [MD5]: https://en.wikipedia.org/wiki/MD5
28
29mod chunk;
30mod chunk_processor;
31mod conversions;
32mod hash;
33mod hash_compute_state;
34mod md5_error;
35
36use chunk::CHUNK_SIZE_BYTES;
37
38pub use crate::hash::Hash;
39pub use crate::md5_error::Md5Error;
40
41use crate::chunk_processor::ChunkProcessor;
42
43use std::io::Read;
44
45/// A hasher thath computes the MD5 hash of a given list of chunks.
46///
47/// Each chunk is defined as a buffer of type `[u8; 64]`.
48///
49/// Provides conveniente functions to compute the MD5 hash of various sources without having to
50/// create and manage an instance.
51#[derive(Default)]
52pub struct Md5Hasher {
53    processor: ChunkProcessor,
54}
55
56impl Md5Hasher {
57    /// Computes and returns the hash of the data that can be readed from the `input`.
58    ///
59    /// # Errors
60    ///
61    /// If there's any I/O error while reading the `input` an error is returned.
62    ///
63    /// # Examples
64    ///
65    /// ```
66    /// use std::io::Cursor;
67    /// use ya_md5::Md5Hasher;
68    ///
69    /// let hash = Md5Hasher::hash(&mut Cursor::new("hello world".as_bytes()))
70    ///     .expect("Unexpected error reading from a cursor");
71    /// let result = format!("{}", hash);
72    /// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
73    /// ```
74    pub fn hash(input: &mut dyn Read) -> Result<Hash, Md5Error> {
75        let mut hasher = Self::default();
76        let mut buffer = [0; CHUNK_SIZE_BYTES];
77        loop {
78            let readed = input.read(&mut buffer).map_err(Md5Error::from)?;
79            if readed == 0 {
80                break;
81            }
82            hasher.update(&buffer[..readed]);
83        }
84        Ok(hasher.finalize())
85    }
86
87    /// Computes and returns the hash of the data in the slice.
88    ///
89    /// # Examples
90    /// ```
91    /// use ya_md5::Md5Hasher;
92    ///
93    /// let hash = Md5Hasher::hash_slice("hello world".as_bytes());
94    /// let result = format!("{}", hash);
95    /// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
96    /// ```
97    pub fn hash_slice(data: &[u8]) -> Hash {
98        let mut hasher = Self::default();
99        hasher.update(data);
100        hasher.finalize()
101    }
102
103    /// Computes and returns the hash of the data in the `Vec`.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// use ya_md5::Md5Hasher;
109    ///
110    /// let hash = Md5Hasher::hash_vec(&Vec::from("hello world".as_bytes()));
111    /// let result = format!("{}", hash);
112    /// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
113    /// ```
114    pub fn hash_vec(data: &Vec<u8>) -> Hash {
115        Self::hash_slice(data.as_slice())
116    }
117
118    /// Computes and returns the hash of the data in the string slice.
119    ///
120    /// # Examples
121    /// ```
122    /// use ya_md5::Md5Hasher;
123    ///
124    /// let hash = Md5Hasher::hash_str("hello world");
125    /// let result = format!("{}", hash);
126    /// assert_eq!(result, "5eb63bbbe01eeed093cb22bb8f5acdc3");
127    /// ```
128    pub fn hash_str(data: &str) -> Hash {
129        Self::hash_slice(data.as_bytes())
130    }
131
132    /// Process a single chunk and use it to compute the internal state.
133    pub fn update(&mut self, data: impl AsRef<[u8]>) {
134        self.processor.update(data);
135    }
136
137    /// Computes the hash of the internal state of the instance, consuming the instance in the
138    /// process.
139    pub fn finalize(self) -> Hash {
140        self.processor.finalize()
141    }
142}