c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

commit 7f12199f569d7b218379d2bbdd087804e9d5bd85
parent 5a293e9fb39a06f1a25acee36039f6242e702294
Author: Gavin  Peacock <gpeacock@adobe.com>
Date:   Fri, 17 Jun 2022 09:55:36 -0700

(MINOR) Clean up client example; update actions and schema (#51)

cleanup client-example - update actions & schema
Diffstat:
Msdk/examples/client/client.rs | 43+++++++++++++++++++++++--------------------
Msdk/src/assertions/actions.rs | 24++++++++++++++----------
Msdk/src/assertions/schema_org.rs | 18+++++++++---------
3 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/sdk/examples/client/client.rs b/sdk/examples/client/client.rs @@ -16,7 +16,7 @@ use anyhow::Result; use c2pa::{ - assertions::{c2pa_action, labels, Action, Actions, CreativeWork}, + assertions::{c2pa_action, labels, Action, Actions, CreativeWork, SchemaDotOrgPerson}, get_temp_signer, Ingredient, Manifest, ManifestStore, }; use std::path::PathBuf; @@ -29,8 +29,6 @@ fn fixture_path(file_name: &str) -> PathBuf { } const GENERATOR: &str = "test_app/0.1"; -const CREATIVE_WORK_URL: &str = r#"{"@type":"CreativeWork","@context":"https://schema.org","url":"http://contentauthenticity.org"}"#; - const INDENT_SPACE: usize = 2; // Example for reading the contents of a manifest store, recursively showing nested manifests @@ -87,32 +85,37 @@ fn show_manifest(manifest_store: &ManifestStore, manifest_label: &str, level: us pub fn main() -> Result<()> { let args: Vec<String> = std::env::args().collect(); - if args.len() != 3 { - println!("This requires a path to a source image and a path to an output file. Both must be jpg or png files."); - return Ok(()); - } - let source = PathBuf::from(&args[1]); - let dest = PathBuf::from(&args[2]); - - // create a new Manifest - let mut manifest = Manifest::new(GENERATOR.to_owned()); + // allow passing in source and dest paths or use defaults + let (src, dst) = match args.len() >= 3 { + true => (args[1].as_str(), args[2].as_str()), + false => ( + "sdk/tests/fixtures/earth_apollo17.jpg", + "target/tmp/client.jpg", + ), + }; + let source = PathBuf::from(src); + let dest = PathBuf::from(dst); // if a filepath was provided on the command line, read it as a parent file - let parent = Ingredient::from_file(source)?; - let source = PathBuf::from(&args[1]); + let parent = Ingredient::from_file(source.as_path())?; // create an action assertion stating that we imported this file let actions = Actions::new().add_action( Action::new(c2pa_action::PLACED) - .set_parameter("identifier".to_owned(), parent.instance_id().to_owned())?, + .set_parameter("identifier", parent.instance_id().to_owned())?, ); - manifest.add_assertion(&actions)?; - // set the parent ingredient - manifest.set_parent(parent)?; + // build a creative work assertion + let creative_work = + CreativeWork::new().add_author(SchemaDotOrgPerson::new().set_name("me")?)?; - let creative_work = CreativeWork::from_json_str(CREATIVE_WORK_URL)?; - manifest.add_assertion(&creative_work)?; + // create a new Manifest + let mut manifest = Manifest::new(GENERATOR.to_owned()); + // add parent and assertions + manifest + .set_parent(parent)? + .add_assertion(&actions)? + .add_assertion(&creative_work)?; // sign and embed into the target file let cert_dir = fixture_path("certs"); diff --git a/sdk/src/assertions/actions.rs b/sdk/src/assertions/actions.rs @@ -165,14 +165,14 @@ impl Action { /// Sets the timestamp for when the action occurred. /// /// This timestamp must be in ISO-8601 date. - pub fn set_when(mut self, when: &str) -> Self { - self.when = Some(when.to_owned()); + pub fn set_when<S: Into<String>>(mut self, when: S) -> Self { + self.when = Some(when.into()); self } /// Sets the software agent that performed the action. - pub fn set_software_agent(mut self, software_agent: &str) -> Self { - self.software_agent = Some(software_agent.to_owned()); + pub fn set_software_agent<S: Into<String>>(mut self, software_agent: S) -> Self { + self.software_agent = Some(software_agent.into()); self } @@ -185,24 +185,28 @@ impl Action { /// Sets the value of the `xmpMM:InstanceID` property for the /// modified (output) resource. - pub fn set_instance_id(mut self, id: &str) -> Self { - self.instance_id = Some(id.to_owned()); + pub fn set_instance_id<S: Into<String>>(mut self, id: S) -> Self { + self.instance_id = Some(id.into()); self } /// Sets the additional parameters for this action. /// /// These vary by the type of action. - pub fn set_parameter<T: Serialize>(mut self, key: String, value: T) -> Result<Self> { + pub fn set_parameter<S: Into<String>, T: Serialize>( + mut self, + key: S, + value: T, + ) -> Result<Self> { let value = serde_json::to_value(value).map_err(|_| Error::AssertionEncoding)?; self.parameters = Some(match self.parameters { Some(mut parameters) => { - parameters.insert(key, value); + parameters.insert(key.into(), value); parameters } None => { let mut p = HashMap::new(); - p.insert(key, value); + p.insert(key.into(), value); p } }); @@ -219,7 +223,7 @@ impl Action { /// An `Actions` assertion provides information on edits and other /// actions taken that affect the asset’s content. /// -/// This assertion contains a list of [`Action`]s, each one declaring +/// This assertion contains a list of [`Action`], each one declaring /// what took place on the asset, when it took place, along with possible /// other information such as what software performed the action. /// diff --git a/sdk/src/assertions/schema_org.rs b/sdk/src/assertions/schema_org.rs @@ -142,7 +142,7 @@ impl SchemaDotOrgPerson { Self(SchemaDotOrg::new(Self::PERSON.to_owned())) } - pub fn new_person(name: String, identifier: String) -> Result<Self> { + pub fn new_person<S: Into<String>>(name: S, identifier: S) -> Result<Self> { Self(SchemaDotOrg::new(Self::PERSON.to_owned())) .set_name(name)? .set_identifier(identifier) @@ -154,16 +154,16 @@ impl SchemaDotOrgPerson { } /// insert key / value pair - pub fn insert<T: Serialize>(self, key: String, value: T) -> Result<Self> { - self.0.insert(key, value).map(Self) + pub fn insert<S: Into<String>, T: Serialize>(self, key: S, value: T) -> Result<Self> { + self.0.insert(key.into(), value).map(Self) } // add a value to a Vec stored at key - pub fn insert_push<T>(self, key: String, value: T) -> Result<Self> + pub fn insert_push<S: Into<String>, T>(self, key: S, value: T) -> Result<Self> where T: Serialize + DeserializeOwned, { - self.0.insert_push(key, value).map(Self) + self.0.insert_push(key.into(), value).map(Self) } // get name field if it exists @@ -171,8 +171,8 @@ impl SchemaDotOrgPerson { self.get(Self::NAME) } - pub fn set_name(self, author: String) -> Result<Self> { - self.insert(Self::NAME.to_owned(), author) + pub fn set_name<S: Into<String>>(self, author: S) -> Result<Self> { + self.insert(Self::NAME.to_string(), author.into()) } // get identifier field if it exists @@ -180,8 +180,8 @@ impl SchemaDotOrgPerson { self.get(Self::IDENTIFIER) } - pub fn set_identifier(self, identifier: String) -> Result<Self> { - self.insert(Self::IDENTIFIER.to_owned(), identifier) + pub fn set_identifier<S: Into<String>>(self, identifier: S) -> Result<Self> { + self.insert(Self::IDENTIFIER.to_owned(), identifier.into()) } pub fn add_credential(self, credential: HashedUri) -> Result<Self> {