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:
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);
}