kitab

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | LICENSE

commit 3dde9494824bd75214b7a830375c849d9b64a7d8
parent 526fba3b6631caf3cf1a37e29ec5744fabe6ace0
Author: lash <dev@holbrook.no>
Date:   Mon, 25 Jul 2022 14:02:27 +0000

Allow import from known digest types

Diffstat:
Asrc/digest.rs | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib.rs | 2++
Msrc/meta.rs | 33++++++++++++++++++++++++---------
Msrc/rdf.rs | 22++++++++++++++++++----
4 files changed, 171 insertions(+), 13 deletions(-)

diff --git a/src/digest.rs b/src/digest.rs @@ -0,0 +1,127 @@ +use crate::error::ParseError; + +use sha2::{ + Sha512, + Sha256, + Digest, +}; + +use log::error; + +pub enum RecordDigest { + Sha512(Vec<u8>), + Sha256(Vec<u8>), + SwarmHash(Vec<u8>), + Empty, +} + + + +pub fn from_vec(v: Vec<u8>) -> Result<RecordDigest, ParseError> { + let sz = Sha512::output_size(); + if v.len() != sz { + return Err(ParseError); + } + Ok(RecordDigest::Sha512(v)) +} + +pub fn from_urn(urn: &str) -> Result<RecordDigest, ParseError> { + let mut v = urn.split(":"); + let r = match v.next() { + Some("sha512") => { + let digest_hex = v.next().unwrap(); + let digest = hex::decode(digest_hex).unwrap(); + match from_vec(digest) { + Ok(vv) => { + vv + }, + Err(e) => { + return Err(ParseError); + }, + } + }, + Some("sha256") => { + let digest_hex = v.next().unwrap(); + let digest = hex::decode(digest_hex).unwrap(); + + let sz = Sha256::output_size(); + if digest.len() != sz { + return Err(ParseError); + } + + RecordDigest::Sha256(digest) + }, + Some("bzz") => { + let digest_hex = v.next().unwrap(); + let digest = hex::decode(digest_hex).unwrap(); + + if digest.len() != 32 { + return Err(ParseError); + } + + RecordDigest::SwarmHash(digest) + }, + Some("") => { + RecordDigest::Empty + }, + Some(_) => { + return Err(ParseError); + }, + None => { + RecordDigest::Empty + }, + }; + Ok(r) +} + +#[cfg(test)] +mod tests { + use super::from_urn; + use super::ParseError; + + #[test] + fn test_digest_urn_parse() { + match from_urn("sha512:deadbeef") { + Ok(v) => { + panic!("expected fail"); + }, + _ => {}, + }; + match from_urn("sha512:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") { + Ok(v) => {}, + _ => { + panic!("expected pass"); + }, + }; + match from_urn("sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") { + Ok(v) => {}, + _ => { + panic!("expected pass"); + }, + }; + match from_urn("bzz:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") { + Ok(v) => {}, + _ => { + panic!("expected pass"); + }, + }; + match from_urn("foo:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") { + Ok(v) => { + panic!("expected fail"); + }, + _ => {}, + }; + match from_urn("foo:deadbeef") { + Ok(v) => { + panic!("expected fail"); + }, + _ => {}, + }; + match from_urn("") { + Ok(v) => {}, + _ => { + panic!("expected pass"); + }, + }; + } +} diff --git a/src/lib.rs b/src/lib.rs @@ -12,6 +12,8 @@ pub mod biblatex; pub mod error; +pub mod digest; + #[cfg(test)] mod tests { use env_logger; diff --git a/src/meta.rs b/src/meta.rs @@ -37,6 +37,8 @@ use crate::dc::{ DC_XATTR_MEDIATYPE, }; +use crate::digest; + use log::{ debug, }; @@ -49,7 +51,7 @@ pub type FilePath = String; pub struct MetaData { dc: DCMetaData, - digest: Vec<u8>, + digest: digest::RecordDigest, local_name: Option<FileName>, comment: String, publish_date: PublishDate, @@ -81,7 +83,7 @@ impl MetaData { let mut m = MetaData{ dc: dc, - digest: vec!(), + digest: digest::RecordDigest::Empty, comment: String::new(), local_name: filename, publish_date: (0, 0, 0), @@ -96,7 +98,7 @@ impl MetaData { let dc = DCMetaData::new("", "", EntryType::Unknown(String::new())); MetaData{ dc: dc, - digest: vec!(), + digest: digest::RecordDigest::Empty, comment: String::new(), //local_name: filepath.to_str().unwrap().to_string(), local_name: None, @@ -114,11 +116,11 @@ impl MetaData { } pub fn set_fingerprint(&mut self, fingerprint: Vec<u8>) { - let sz = Sha512::output_size(); - if fingerprint.len() != sz { - panic!("wrong digest size, must be {}", sz); - } - self.digest = fingerprint; + self.digest = digest::from_vec(fingerprint).unwrap(); + } + + pub fn set_fingerprint_urn(&mut self, urn: &str) { + self.digest = digest::from_urn(urn).unwrap(); } pub fn title(&self) -> String { @@ -174,7 +176,20 @@ impl MetaData { } pub fn fingerprint(&self) -> String { - hex::encode(&self.digest) + match &self.digest { + digest::RecordDigest::Empty => { + return String::new(); + }, + digest::RecordDigest::Sha512(v) => { + return hex::encode(&v); + }, + digest::RecordDigest::Sha256(v) => { + return hex::encode(&v); + }, + digest::RecordDigest::SwarmHash(v) => { + return hex::encode(&v); + }, + } } pub fn from_xattr(filepath: &path::Path) -> MetaData { diff --git a/src/rdf.rs b/src/rdf.rs @@ -32,6 +32,7 @@ use log::{ error, }; +use crate::digest; use crate::meta::MetaData; use crate::error::ParseError; use crate::dc::{ @@ -118,17 +119,30 @@ pub fn write(entry: &MetaData, w: impl Write) -> Result<usize, std::io::Error> { fn handle_parse_match(metadata: &mut MetaData, triple: Triple) -> Result<(), RdfError> { let subject_iri = triple.subject.to_string(); let l = subject_iri.len()-1; + //let subject = &subject_iri[1..l]; let subject = &subject_iri[1..l]; + match &subject[0..4] { + "urn:" => {}, + _ => { + return Err(RdfError::UrnError(UrnError::InvalidNid)); + }, + }; + let digest_urn = match digest::from_urn(&subject[4..]) { + Err(e) => { + error!("error {:?}", &subject); + return Err(RdfError::UrnError(UrnError::InvalidNid)); + }, + Ok(v) => { + &subject[4..] + }, + }; let subject_urn = Urn::from_str(subject).unwrap(); - if subject_urn.nid() != "sha512" { - return Err(RdfError::UrnError(UrnError::InvalidNid)); - } let v = subject_urn.nss(); let b = hex::decode(&v).unwrap(); if metadata.fingerprint().len() == 0 { debug!("setting fingerprint {}", v); - metadata.set_fingerprint(b); + metadata.set_fingerprint_urn(digest_urn); } else if metadata.fingerprint() != v { return Err(RdfError::HashMismatchError); }