diff options
author | evuez <julien@mulga.net> | 2024-04-03 22:43:16 +0200 |
---|---|---|
committer | evuez <julien@mulga.net> | 2024-04-03 22:43:16 +0200 |
commit | 43e1a12b5bce11b4a28a53acca243e35c2be6d3e (patch) | |
tree | 07d64823718bfee063ab7b3d5721ac1e950ae17c /src/server/blobref.rs | |
download | carton-43e1a12b5bce11b4a28a53acca243e35c2be6d3e.tar.gz |
Initial commit
Diffstat (limited to 'src/server/blobref.rs')
-rw-r--r-- | src/server/blobref.rs | 62 |
1 files changed, 62 insertions, 0 deletions
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<T> = std::result::Result<T, Error>; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)] +pub struct BlobRef(String); + +impl BlobRef { + pub fn from_str(s: &str) -> Result<Self> { + 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<rusqlite::types::ToSqlOutput<'_>> { + Ok(ToSqlOutput::Borrowed(rusqlite::types::ValueRef::Text( + self.0.as_bytes(), + ))) + } +} + +impl FromSql for BlobRef { + fn column_result(value: rusqlite::types::ValueRef<'_>) -> FromSqlResult<Self> { + let v: String = FromSql::column_result(value)?; + BlobRef::from_str(&v).map_err(|_| FromSqlError::InvalidType) + } +} |