From 43e1a12b5bce11b4a28a53acca243e35c2be6d3e Mon Sep 17 00:00:00 2001 From: evuez Date: Wed, 3 Apr 2024 22:43:16 +0200 Subject: Initial commit --- src/server/blobref.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/server/blobref.rs (limited to 'src/server/blobref.rs') diff --git a/src/server/blobref.rs b/src/server/blobref.rs new file mode 100644 index 0000000..7d9fa66 --- /dev/null +++ b/src/server/blobref.rs @@ -0,0 +1,62 @@ +use crate::common::hash::{self, Hasher}; +use rusqlite::types::{FromSql, FromSqlError}; +use rusqlite::{ + types::{FromSqlResult, ToSqlOutput}, + ToSql, +}; +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use std::path::PathBuf; +use std::str::FromStr; + +#[derive(Debug)] +pub enum Error { + InvalidHash(hash::Error), +} + +type Result = std::result::Result; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)] +pub struct BlobRef(String); + +impl BlobRef { + pub fn from_str(s: &str) -> Result { + hash::Hash::from_str(s).map_err(Error::InvalidHash)?; + Ok(Self(s.to_string())) + } + + pub fn for_bytes(bytes: &[u8]) -> Self { + let mut hasher = Hasher::default(); + hasher.update(bytes); + BlobRef(hasher.finish().to_base32()) + } + + pub(super) fn path(&self) -> PathBuf { + let mut buf = PathBuf::new(); + buf.push(&self.0[0..4]); + buf.push(&self.0[4..]); + + buf + } +} + +impl Display for BlobRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "blobref:{}", self.0) + } +} + +impl ToSql for BlobRef { + fn to_sql(&self) -> rusqlite::Result> { + Ok(ToSqlOutput::Borrowed(rusqlite::types::ValueRef::Text( + self.0.as_bytes(), + ))) + } +} + +impl FromSql for BlobRef { + fn column_result(value: rusqlite::types::ValueRef<'_>) -> FromSqlResult { + let v: String = FromSql::column_result(value)?; + BlobRef::from_str(&v).map_err(|_| FromSqlError::InvalidType) + } +} -- cgit v1.2.3