2021-02-21 19:51:23 +01:00
|
|
|
use crate::addressing::Address;
|
2022-09-12 23:30:43 +02:00
|
|
|
use anyhow::Result;
|
2021-02-21 19:43:28 +01:00
|
|
|
use diesel::backend::Backend;
|
|
|
|
use diesel::deserialize::FromSql;
|
|
|
|
use diesel::sqlite::Sqlite;
|
|
|
|
use diesel::{deserialize, sql_types};
|
2020-09-07 21:21:54 +02:00
|
|
|
use filebuffer::FileBuffer;
|
2022-09-12 23:30:43 +02:00
|
|
|
use multihash::Hasher;
|
2021-02-21 19:51:23 +01:00
|
|
|
use serde::{ser, Serialize, Serializer};
|
2023-04-20 16:02:41 +02:00
|
|
|
use std::path::{Path};
|
2022-10-23 15:59:10 +02:00
|
|
|
use tracing::trace;
|
2020-09-07 21:21:54 +02:00
|
|
|
|
2021-12-04 18:33:40 +01:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, FromSqlRow, Hash)]
|
2020-09-07 21:21:54 +02:00
|
|
|
pub struct Hash(pub Vec<u8>);
|
|
|
|
|
2021-02-19 20:27:30 +01:00
|
|
|
impl AsRef<[u8]> for Hash {
|
|
|
|
fn as_ref(&self) -> &[u8] {
|
|
|
|
self.0.as_ref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-21 19:43:28 +01:00
|
|
|
impl FromSql<sql_types::Binary, Sqlite> for Hash {
|
|
|
|
fn from_sql(bytes: Option<&<Sqlite as Backend>::RawValue>) -> deserialize::Result<Self> {
|
|
|
|
Ok(Hash(Vec::from(not_none!(bytes).read_blob())))
|
|
|
|
}
|
|
|
|
}
|
2020-09-07 21:21:54 +02:00
|
|
|
|
2021-02-21 19:51:23 +01:00
|
|
|
impl Serialize for Hash {
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
|
|
|
serializer.serialize_str(
|
2022-01-26 16:55:23 +01:00
|
|
|
b58_encode(
|
2021-02-21 19:51:23 +01:00
|
|
|
Address::Hash(self.clone())
|
|
|
|
.encode()
|
|
|
|
.map_err(ser::Error::custom)?,
|
|
|
|
)
|
|
|
|
.as_str(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-07 21:21:54 +02:00
|
|
|
pub trait Hashable {
|
|
|
|
fn hash(&self) -> Result<Hash>;
|
|
|
|
}
|
|
|
|
|
2022-01-18 16:59:59 +01:00
|
|
|
impl Hashable for Path {
|
|
|
|
fn hash(self: &Path) -> Result<Hash> {
|
2021-12-04 16:45:16 +01:00
|
|
|
trace!("Hashing {:?}...", self);
|
2020-09-07 21:21:54 +02:00
|
|
|
let fbuffer = FileBuffer::open(self)?;
|
2021-12-04 16:45:16 +01:00
|
|
|
trace!("Finished hashing {:?}...", self);
|
2020-09-07 21:21:54 +02:00
|
|
|
Ok(hash(&fbuffer))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn hash<T: AsRef<[u8]>>(input: T) -> Hash {
|
2022-09-12 23:30:43 +02:00
|
|
|
let mut hasher = multihash::Sha2_256::default();
|
|
|
|
hasher.update(input.as_ref());
|
|
|
|
Hash(Vec::from(hasher.finalize()))
|
2020-09-07 21:21:54 +02:00
|
|
|
}
|
|
|
|
|
2022-01-26 16:55:23 +01:00
|
|
|
pub fn b58_encode<T: AsRef<[u8]>>(vec: T) -> String {
|
2022-09-12 23:30:43 +02:00
|
|
|
multibase::encode(multibase::Base::Base58Btc, vec.as_ref())
|
2020-09-07 21:21:54 +02:00
|
|
|
}
|
|
|
|
|
2022-09-12 23:30:43 +02:00
|
|
|
pub fn b58_decode<T: AsRef<str>>(input: T) -> Result<Vec<u8>> {
|
|
|
|
let input = input.as_ref();
|
|
|
|
let (_base, data) = multibase::decode(input)?;
|
|
|
|
Ok(data)
|
2020-09-07 21:21:54 +02:00
|
|
|
}
|
2021-02-19 22:27:54 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2022-01-26 16:55:23 +01:00
|
|
|
use crate::util::hash::{b58_decode, b58_encode};
|
2021-02-19 22:27:54 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_encode_decode() {
|
|
|
|
let content = "Hello, World!".as_bytes();
|
|
|
|
|
2022-01-26 16:55:23 +01:00
|
|
|
let encoded = b58_encode(content);
|
|
|
|
let decoded = b58_decode(encoded);
|
2021-02-19 22:27:54 +01:00
|
|
|
|
|
|
|
assert!(decoded.is_ok());
|
|
|
|
|
|
|
|
assert_eq!(content, decoded.unwrap());
|
|
|
|
}
|
|
|
|
}
|