commit b146bb7545086656941ae452428aef8c1b3ef6d6
parent 3726b0aaddf3f33b3ab50ddc3cf3698212aa8a4f
Author: Gavin Peacock <gpeacock@adobe.com>
Date: Fri, 2 Dec 2022 14:54:10 -0800
Fixes support for instanceId on action and generate parameters.ingredient field when possible (#158)
* Inject action.property.Ingredient based on instance_id
* fixes setting ingredients on actions
Update make_test_images
Diffstat:
3 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/make_test_images/src/make_test_images.rs b/make_test_images/src/make_test_images.rs
@@ -218,8 +218,7 @@ impl MakeTestImages {
let parent = Ingredient::from_file_with_options(src_path, &ImageOptions::new())?;
actions = actions.add_action(
- Action::new(c2pa_action::OPENED)
- .set_parameter("identifier".to_owned(), parent.instance_id().to_owned())?,
+ Action::new(c2pa_action::OPENED).set_instance_id(parent.instance_id()),
);
manifest.set_parent(parent)?;
@@ -279,11 +278,9 @@ impl MakeTestImages {
// create and add the ingredient
let ingredient =
Ingredient::from_file_with_options(ing_path, &ImageOptions::new())?;
- actions =
- actions.add_action(Action::new(c2pa_action::PLACED).set_parameter(
- "identifier".to_owned(),
- ingredient.instance_id().to_owned(),
- )?);
+ actions = actions.add_action(
+ Action::new(c2pa_action::PLACED).set_instance_id(ingredient.instance_id()),
+ );
manifest.add_ingredient(ingredient);
x += width;
diff --git a/sdk/src/assertions/actions.rs b/sdk/src/assertions/actions.rs
@@ -66,7 +66,7 @@ pub mod c2pa_action {
/// the action.
///
/// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_actions>.
-#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)]
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct Action {
/// The label associated with this action. See ([`c2pa_action`]).
action: String,
@@ -88,7 +88,7 @@ pub struct Action {
changed: Option<String>,
/// The value of the `xmpMM:InstanceID` property for the modified (output) resource.
- #[serde(rename = "InstanceId", skip_serializing_if = "Option::is_none")]
+ #[serde(rename = "instanceId", skip_serializing_if = "Option::is_none")]
instance_id: Option<String>,
/// Additional parameters of the action. These vary by the type of action.
@@ -279,6 +279,12 @@ impl Actions {
self.metadata.as_ref()
}
+ /// Internal method to update actions to meet spec requirements
+ pub(crate) fn update_action(mut self, index: usize, action: Action) -> Self {
+ self.actions[index] = action;
+ self
+ }
+
/// Adds an [`Action`] to this assertion's list of actions.
pub fn add_action(mut self, action: Action) -> Self {
self.actions.push(action);
@@ -463,7 +469,6 @@ pub mod tests {
#[test]
fn test_binary_round_trip() {
let assertion = Actions::new()
- // .set_dictionary("http://testdictionary")
.add_action(
Action::new("c2pa.cropped")
.set_parameter(
@@ -515,7 +520,8 @@ pub mod tests {
}
},
{
- "action": "c2pa.edited",
+ "action": "c2pa.opened",
+ "instanceId": "xmp.iid:7b57930e-2f23-47fc-affe-0400d70b738d",
"parameters": {
"description": "import"
},
diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs
@@ -591,9 +591,13 @@ impl Manifest {
}
}
+ let mut ingredient_map = HashMap::new();
// add all ingredients to the claim
for ingredient in &self.ingredients {
- ingredient.add_to_claim(&mut claim, self.redactions.clone())?;
+ ingredient_map.insert(
+ ingredient.instance_id(),
+ ingredient.add_to_claim(&mut claim, self.redactions.clone())?,
+ );
}
let salt = DefaultSalt::default();
@@ -602,9 +606,33 @@ impl Manifest {
for manifest_assertion in &self.assertions {
match manifest_assertion.label() {
Actions::LABEL => {
- let actions: Actions = manifest_assertion.to_assertion()?;
- // todo: fixup parameters field from instance_id to ingredient uri for
- // c2pa.transcoded, c2pa.repackaged, and c2pa.placed action
+ let mut actions: Actions = manifest_assertion.to_assertion()?;
+
+ // fixup parameters field from instance_id to ingredient uri
+ let needs_ingredient: Vec<(usize, crate::assertions::Action)> = actions
+ .actions()
+ .iter()
+ .enumerate()
+ .filter_map(|(i, a)| {
+ if a.instance_id().is_some() && a.get_parameter("ingredient").is_none()
+ {
+ Some((i, a.clone()))
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ for (index, action) in needs_ingredient {
+ if let Some(id) = action.instance_id() {
+ if let Some(hash_url) = ingredient_map.get(id) {
+ let update =
+ action.set_parameter("ingredient", hash_url.clone())?;
+ actions = actions.update_action(index, update);
+ }
+ }
+ }
+
claim.add_assertion(&actions)
}
CreativeWork::LABEL => {