#[cfg(feature = "async")]
pub mod async_digest;
#[cfg(feature = "native_openssl")]
mod openssl_sha256;
#[cfg(feature = "native_openssl")]
use crate::openssl_sha256::OpenSslSha256;
#[cfg(feature = "async")]
pub use async_digest::*;
use sha2::digest::Output;
use sha2::{Digest, Sha256};
use std::fmt::Debug;
use std::fs;
use std::io;
use std::io::{BufReader, Read};
use std::path::Path;
#[cfg(test)]
mod tests;
pub fn digest<D: Sha256Digest>(input: D) -> String {
input.digest()
}
pub fn try_digest<D: TrySha256Digest>(input: D) -> Result<String, D::Error> {
input.digest()
}
#[deprecated(since = "1.1.0", note = "Use new function `digest()` instead")]
pub fn digest_bytes(input: &[u8]) -> String {
__digest__(input)
}
#[deprecated(since = "1.1.0", note = "Use new function `try_digest()` instead")]
pub fn digest_file<P: AsRef<Path>>(path: P) -> Result<String, io::Error> {
let bytes = fs::read(path)?;
Ok(__digest__(&bytes))
}
pub trait Sha256Digest {
fn digest(self) -> String;
}
#[async_trait::async_trait]
pub trait TrySha256Digest {
type Error: Debug;
fn digest(self) -> Result<String, Self::Error>;
#[cfg(feature = "async")]
async fn async_digest(self) -> Result<String, Self::Error>;
#[cfg(feature = "native_openssl")]
async fn async_openssl_digest(self) -> Result<String, Self::Error>;
}
impl<const N: usize> Sha256Digest for &[u8; N] {
fn digest(self) -> String {
__digest__(self)
}
}
impl Sha256Digest for &[u8] {
fn digest(self) -> String {
__digest__(self)
}
}
impl Sha256Digest for &Vec<u8> {
fn digest(self) -> String {
__digest__(self)
}
}
impl Sha256Digest for Vec<u8> {
fn digest(self) -> String {
__digest__(&self)
}
}
impl Sha256Digest for String {
fn digest(self) -> String {
__digest__(self.as_bytes())
}
}
impl Sha256Digest for &str {
fn digest(self) -> String {
__digest__(self.as_bytes())
}
}
impl Sha256Digest for char {
fn digest(self) -> String {
__digest__(self.encode_utf8(&mut [0; 4]).as_bytes())
}
}
impl Sha256Digest for &mut &str {
fn digest(self) -> String {
__digest__(self.as_bytes())
}
}
impl Sha256Digest for &String {
fn digest(self) -> String {
__digest__(self.as_bytes())
}
}
#[async_trait::async_trait]
impl<P> TrySha256Digest for P
where
P: AsRef<Path> + Send,
{
type Error = io::Error;
fn digest(self) -> Result<String, Self::Error> {
let f = fs::File::open(self)?;
let reader = BufReader::new(f);
let sha = Sha256::new();
calc(reader, sha)
}
#[cfg(feature = "async")]
async fn async_digest(self) -> Result<String, Self::Error> {
let f = tokio::fs::File::open(self).await?;
let reader = tokio::io::BufReader::new(f);
let sha = Sha256::new();
async_calc(reader, sha).await
}
#[cfg(all(feature = "async", feature = "native_openssl"))]
async fn async_openssl_digest(self) -> Result<String, Self::Error> {
let f = tokio::fs::File::open(self).await?;
let reader = tokio::io::BufReader::new(f);
let sha = OpenSslSha256::new();
async_calc(reader, sha).await
}
}
fn __digest__(data: &[u8]) -> String {
hex::encode(Sha256::digest(data))
}
trait CalculatorInput {
fn read_inner(&mut self, buf: &mut [u8]) -> std::io::Result<usize>;
}
impl<T> CalculatorInput for T
where
T: Read,
{
fn read_inner(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.read(buf)
}
}
pub trait CalculatorSelector {
type FinishType: AsRef<[u8]>;
fn update_inner(&mut self, data: &[u8]);
fn finish_inner(self) -> Self::FinishType;
}
impl CalculatorSelector for Sha256 {
type FinishType = Output<Sha256>;
fn update_inner(&mut self, data: &[u8]) {
self.update(data)
}
fn finish_inner(self) -> Self::FinishType {
self.finalize()
}
}
fn calc<I, S>(mut input: I, mut selector: S) -> io::Result<String>
where
I: CalculatorInput,
S: CalculatorSelector,
{
let mut buf = [0u8; 1024];
loop {
let len = input.read_inner(&mut buf)?;
if len == 0 {
break;
}
selector.update_inner(&buf[0..len]);
}
let hash = selector.finish_inner();
Ok(hex::encode(hash))
}