< 返回我的博客

Borber 发表于 2021-12-24 10:46

Tags:hash, blake3

粗略测试了一下, 感觉比md5更快

源自 https://github.com/BLAKE3-team/BLAKE3/blob/master/b3sum/src/main.rs

简化了一点点, 加深自己的印象,

  1. OutputReader 有bug, 换成了 Hash.
  2. 原为cli程序, 现去除菜单,设置之类的实体, 只提取单个文件获取hash
use anyhow::Result;
use std::fs::File;
use std::{cmp, io};
use std::io::prelude::*;
use std::path::Path;

const DERIVE_KEY: &str = "BORBER";

enum Input {
    Mmap(io::Cursor<memmap::Mmap>),
    File(File)
}

impl Input {
    fn open(path: &Path) -> Result<Self> {
        let file = File::open(path)?;
        if let Some(mmap) = maybe_memmap_file(&file)? {
            return Ok(Self::Mmap(io::Cursor::new(mmap)));
        }
        Ok(Self::File(file))
    }

    fn hash(&mut self) -> Result<blake3::Hash> {
        let mut hasher = blake3::Hasher::new_derive_key(DERIVE_KEY);
        match self {
            Self::Mmap(cursor) => {
                hasher.update_rayon(cursor.get_ref());
            }
            Self::File(file) => {
                copy_wide(file, &mut hasher)?;
            }
        }
        Ok(hasher.finalize())
    }
}

impl Read for Input {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self {
            Self::Mmap(cursor) => cursor.read(buf),
            Self::File(file) => file.read(buf)
        }
    }
}


fn maybe_memmap_file(file: &File) -> Result<Option<memmap::Mmap>> {
    let metadata = file.metadata()?;
    let file_size = metadata.len();
    Ok(if !metadata.is_file() {
        None
    } else if file_size > isize::MAX as u64 {
        None
    } else if file_size == 0 {
        None
    } else if file_size < 16 * 1024 {
        None
    } else {
        let map = unsafe {
            memmap::MmapOptions::new()
                .len(file_size as usize)
                .map(&file)?
        };
        Some(map)
    })
}

fn copy_wide(mut reader: impl Read, hasher: &mut blake3::Hasher) -> io::Result<u64> {
    let mut buffer = [0; 65536];
    let mut total = 0;
    loop {
        match reader.read(&mut buffer) {
            Ok(0) => return Ok(total),
            Ok(n) => {
                hasher.update(&buffer[..n]);
                total += n as u64;
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        }
    }
}

pub fn hash_one(path: &Path) -> Result<String> {
    let mut block = [0; blake3::guts::BLOCK_LEN];
    let mut input = Input::open(path)?;
    let mut output = input.hash()?;
    let s = output.to_string();
    Ok(s)
}
``

评论区

写评论

还没有评论

1 共 0 条评论, 1 页