Skip to content

Commit

Permalink
use base64 to encode/decode raw_metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Song Gao committed May 10, 2024
1 parent c102c01 commit 80bc3be
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ reflink-copy = "0.1.9"
serde = "1.0.130"
serde_derive = "1.0.130"
serde_json = "1.0.68"
base64 = "0.22.0"
base64-serde = "0.7.0"
sha1 = "0.10.5"
sha2 = "0.10.6"
ssri = "9.0.0"
Expand Down
90 changes: 90 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use sha2::Sha256;
use ssri::Integrity;
use walkdir::WalkDir;

use base64_serde::base64_serde_type;

#[cfg(any(feature = "async-std", feature = "tokio"))]
use crate::async_lib::{AsyncBufReadExt, AsyncWriteExt};
use crate::content::path::content_path;
Expand Down Expand Up @@ -50,9 +52,39 @@ struct SerializableMetadata {
time: u128,
size: usize,
metadata: Value,
#[serde(with = "option_base64")]
raw_metadata: Option<Vec<u8>>,
}

base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD);

mod option_base64 {
use super::Base64Standard;
use serde::{Deserialize, Deserializer, Serializer};

pub fn serialize<S>(data: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match data {
Some(data) => Base64Standard::serialize(data, serializer),
None => serializer.serialize_none(),
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
// Create a wrapper type to reuse existing "with" attribute easily
#[derive(Deserialize)]
struct WrappedVecU8(#[serde(with = "Base64Standard")] Vec<u8>);

Option::<WrappedVecU8>::deserialize(deserializer)
.map(|it| it.map(|wrapped_value| wrapped_value.0))
}
}

impl PartialEq for SerializableMetadata {
fn eq(&self, other: &Self) -> bool {
self.key == other.key
Expand Down Expand Up @@ -586,6 +618,64 @@ mod tests {
assert!(!content.exists());
}

#[test]
fn serde_json_raw_metadata() {
let meta = SerializableMetadata {
key: "hello".to_string(),
integrity: Some("sha1-deadbeef".to_string()),
time: 0,
size: 0,
metadata: json!(null),
raw_metadata: Some(vec![b'1', b'2', b'3', b'4']),
};

assert_eq!(
serde_json::to_string(&meta).unwrap(),
"{\"key\":\"hello\",\"integrity\":\"sha1-deadbeef\",\"time\":0,\"size\":0,\"metadata\":null,\"raw_metadata\":\"MTIzNA==\"}"
);

let value = json!(
{
"key": "hello",
"integrity": "sha1-deadbeef",
"time": 0,
"size": 0,
"metadata": null,
"raw_metadata": "MTIzNA=="
}
);

let de_meta: SerializableMetadata = serde_json::from_value(value).unwrap();

assert_eq!(de_meta, meta);
}

#[test]
fn raw_metadata() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().to_owned();
let sri: Integrity = "sha1-deadbeef".parse().unwrap();
let time = 1_234_567;
let raw_metadata = vec![1, 2, 3, 4];
let opts = WriteOpts::new()
.integrity(sri.clone())
.time(time)
.raw_metadata(raw_metadata.clone());
insert(&dir, "hello", opts).unwrap();
let entry = find(&dir, "hello").unwrap().unwrap();
assert_eq!(
entry,
Metadata {
key: String::from("hello"),
integrity: sri,
time: time,
size: 0,
metadata: json!(null),
raw_metadata: Some(raw_metadata),
}
);
}

#[test]
fn round_trip() {
let tmp = tempfile::tempdir().unwrap();
Expand Down

0 comments on commit 80bc3be

Please sign in to comment.