use std::{
io::{Cursor, Seek, Write},
path::PathBuf,
};
use c2pa::{
assertions::{c2pa_action, Action},
Builder, ClaimGeneratorInfo, HashRange, Reader, Result,
};
use serde_json::json;
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("DataHash demo");
user_data_hash_with_placeholder_api()?;
println!("Done with placeholder API");
Ok(())
}
fn user_data_hash_with_placeholder_api() -> Result<()> {
use c2pa::{Context, Settings};
let mut claim_generator = ClaimGeneratorInfo::new("test_app".to_string());
claim_generator.set_version("0.1");
let settings = Settings::new().with_toml(include_str!(
"../tests/fixtures/test_settings_with_cawg_signing.toml"
))?;
let src = "sdk/tests/fixtures/earth_apollo17.jpg";
let format = "image/jpeg";
let source = PathBuf::from(src);
let context = Context::new().with_settings(settings)?.into_shared();
let mut builder = Builder::from_shared_context(&context);
let parent_json = json!({"relationship": "parentOf", "label": "parent_label"});
builder.add_ingredient_from_stream(
parent_json.to_string(),
format,
&mut std::fs::File::open(&source)?,
)?;
builder.add_action(
Action::new(c2pa_action::OPENED).set_parameter("ingredientIds", ["parent_label"])?,
)?;
let jpeg_placeholder = builder.placeholder("image/jpeg")?;
let bytes = std::fs::read(&source)?;
let mut output: Vec<u8> = Vec::with_capacity(bytes.len() + jpeg_placeholder.len());
let manifest_pos = 2;
output.extend_from_slice(&bytes[0..manifest_pos]);
output.extend_from_slice(&jpeg_placeholder);
output.extend_from_slice(&bytes[manifest_pos..]);
let mut output_stream = Cursor::new(output);
builder.set_data_hash_exclusions(vec![HashRange::new(
manifest_pos as u64,
jpeg_placeholder.len() as u64,
)])?;
builder.update_hash_from_stream("image/jpeg", &mut output_stream)?;
let final_manifest = builder.sign_embeddable("image/jpeg")?;
output_stream.seek(std::io::SeekFrom::Start(manifest_pos as u64))?;
output_stream.write_all(&final_manifest)?;
output_stream.rewind()?;
let reader = Reader::default().with_stream("image/jpeg", &mut output_stream)?;
println!("Manifest with placeholder API (supports dynamic assertions):");
println!("{reader}\n");
Ok(())
}