Skip to content

Commit

Permalink
feat: explore with Reader TryInto Value and json formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
gpeacock committed Feb 7, 2025
1 parent 4cb20e3 commit 5d7f8b8
Showing 1 changed file with 114 additions and 0 deletions.
114 changes: 114 additions & 0 deletions sdk/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,14 @@ impl std::fmt::Debug for Reader {
}
}

impl TryInto<serde_json::Value> for Reader {
type Error = crate::Error;

fn try_into(self) -> Result<serde_json::Value> {
serde_json::to_value(self.manifest_store).map_err(crate::Error::JsonError)
}
}

#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
Expand Down Expand Up @@ -526,4 +534,110 @@ pub mod tests {
assert!(std::path::Path::new("../target/reader_folder/manifest.json").exists());
Ok(())
}

use c2pa_crypto::base64;
use serde_json::Value;
fn update_assertions(
mut reader_json: Value,
labels: &[&str],
update: &dyn Fn(&str, &Value) -> Value,
) -> Value {
if let Some(manifests) = reader_json
.get_mut("manifests")
.and_then(|m| m.as_object_mut())
{
for (_manifest_label, manifest) in manifests.iter_mut() {
if let Some(assertions) = manifest
.get_mut("assertions")
.and_then(|a| a.as_array_mut())
{
for assertion in assertions.iter_mut() {
if let Some(lbl) = assertion.get("label").and_then(|l| l.as_str()) {
if labels.contains(&lbl) {
if let Some(data) = assertion.get("data") {
let updated_data = update(lbl, data);
assertion
.as_object_mut()
.unwrap()
.insert("data".to_string(), updated_data);
}
}
}

Check warning on line 565 in sdk/src/reader.rs

View check run for this annotation

Codecov / codecov/patch

sdk/src/reader.rs#L564-L565

Added lines #L564 - L565 were not covered by tests
}
}

Check warning on line 567 in sdk/src/reader.rs

View check run for this annotation

Codecov / codecov/patch

sdk/src/reader.rs#L567

Added line #L567 was not covered by tests
}
}

Check warning on line 569 in sdk/src/reader.rs

View check run for this annotation

Codecov / codecov/patch

sdk/src/reader.rs#L569

Added line #L569 was not covered by tests
reader_json
}

/// convert any hash field in the value to base64
fn hash_to_b64(mut value: Value) -> Value {
fn visitor(value: &mut Value) {
if let Value::Array(hash_arr) = &value["hash"] {
let hash_bytes: Vec<u8> = hash_arr
.iter()
.filter_map(|v| v.as_u64().map(|n| n as u8))
.collect();
let hash_str = base64::encode(&hash_bytes);
value["hash"] = serde_json::Value::String(hash_str);
}
match value {
Value::Object(obj) => {
for v in obj.values_mut() {
visitor(v);
}
}
Value::Array(arr) => {
for v in arr.iter_mut() {
visitor(v);
}
}
_ => {}
}
}
visitor(&mut value);
value
}

#[test]
#[cfg(feature = "file_io")]
fn test_reader_from_file_replace_assertion() -> Result<()> {
let reader = Reader::from_file("tests/fixtures/CA.jpg")?;

let json: serde_json::Value = reader.try_into()?;

let json = update_assertions(
json,
&[
"cawg.identity",
"stds.schema-org.CreativeWork",
"c2pa.actions",
],
&|label, data| {
match label {
"cawg.identity" => serde_json::json!({
"role": "foo",
"identities": []
}),

Check warning on line 621 in sdk/src/reader.rs

View check run for this annotation

Codecov / codecov/patch

sdk/src/reader.rs#L619-L621

Added lines #L619 - L621 were not covered by tests
"stds.schema-org.CreativeWork" => {
let mut data = data.clone();
// insert a new field into the data object
data["role"] = serde_json::json!("investigator");
data
}
"c2pa.actions" => {
let data = data.clone();
hash_to_b64(data)
}
// this should never happen unless you don't handle an assertion in labels
_ => data.clone(),

Check warning on line 633 in sdk/src/reader.rs

View check run for this annotation

Codecov / codecov/patch

sdk/src/reader.rs#L633

Added line #L633 was not covered by tests
}
},
);

// Serialize the updated JSON back to a string
let updated_json_str = serde_json::to_string_pretty(&json)?;
println!("{}", updated_json_str);
Ok(())
}
}

0 comments on commit 5d7f8b8

Please sign in to comment.