use actix::prelude::*; use anyhow::{anyhow, Result}; use filebuffer::FileBuffer; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use tiny_keccak::{Hasher, KangarooTwelve}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Hash(pub Vec); impl AsRef<[u8]> for Hash { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } // impl Hash { // pub fn encode(&self) -> String { // encode(self.0.clone()).into_string() // } // // pub fn decode>(string: T) -> Result { // Ok(Hash(decode(string.as_ref())?)) // } // } // impl std::fmt::Display for Hash { // fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // write!(f, "{}", self.encode()) // } // } pub trait Hashable { fn hash(&self) -> Result; } pub struct HasherWorker; impl Actor for HasherWorker { type Context = SyncContext; } #[derive(Message)] #[rtype(result = "Result")] pub struct ComputeHash { pub path: PathBuf, } impl Handler for HasherWorker { type Result = Result; fn handle(&mut self, msg: ComputeHash, _: &mut Self::Context) -> Self::Result { msg.path.hash() } } impl Hashable for PathBuf { fn hash(self: &PathBuf) -> Result { let fbuffer = FileBuffer::open(self)?; Ok(hash(&fbuffer)) } } pub fn hash>(input: T) -> Hash { let mut k12 = KangarooTwelve::new(b""); k12.update(input.as_ref()); let mut result = [0u8; 256 / 8]; k12.finalize(&mut result); Hash(Vec::from(result)) } pub fn encode>(vec: T) -> String { // multibase base58 format!("z{}", bs58::encode(vec).into_string()) } pub fn decode>(string: T) -> Result> { let string = string.as_ref(); let (base, data) = string.split_at(1); // multibase base58 if base != "z" { Err(anyhow!("data not base58 encoded, bailing")) } else { Ok(bs58::decode(data).into_vec()?) } }