Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add ManifestStore::from_stream #319

Merged
merged 14 commits into from
Oct 13, 2023
2 changes: 1 addition & 1 deletion export_schema/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ rust-version = "1.70.0"
[dependencies]
anyhow = "1.0.40"
c2pa = { path = "../sdk", features = ["file_io", "json_schema"] }
schemars = "0.8.12"
schemars = "0.8.13"
serde_json = "1.0.81"
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ png_pong = "0.8.2"
range-set = "0.0.9"
ring = "0.16.20"
riff = "1.0.1"
schemars = { version = "0.8.12", optional = true }
schemars = { version = "0.8.13", optional = true }
serde = { version = "1.0.137", features = ["derive"] }
serde_bytes = "0.11.5"
serde_cbor = "0.11.1"
Expand Down
6 changes: 4 additions & 2 deletions sdk/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ impl Manifest {
}

/// Embed a signed manifest into a stream using a supplied signer.
/// returns the bytes of the new asset
///
/// Returns the bytes of the new asset
#[deprecated(since = "0.27.2", note = "use embed_to_stream instead")]
pub fn embed_stream(
&mut self,
Expand All @@ -1041,7 +1042,8 @@ impl Manifest {
}

/// Embed a signed manifest into a stream using a supplied signer.
/// returns the bytes of c2pa_manifest that was embedded
///
/// Returns the bytes of c2pa_manifest that was embedded.
pub fn embed_to_stream(
&mut self,
format: &str,
Expand Down
44 changes: 41 additions & 3 deletions sdk/src/manifest_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
store::Store,
utils::base64,
validation_status::{status_for_store, ValidationStatus},
Manifest, Result,
CAIRead, Manifest, Result,
};

#[derive(Serialize)]
Expand All @@ -44,7 +44,7 @@ pub struct ManifestStore {

impl ManifestStore {
/// allocates a new empty ManifestStore
pub(crate) fn new() -> Self {
pub fn new() -> Self {
ManifestStore {
active_manifest: None,
manifests: HashMap::<String, Manifest>::new(),
Expand Down Expand Up @@ -149,14 +149,35 @@ impl ManifestStore {
))
}

/// generate a Store from a format string and bytes
/// Generate a Store from a format string and bytes.
pub fn from_bytes(format: &str, image_bytes: &[u8], verify: bool) -> Result<ManifestStore> {
let mut validation_log = DetailedStatusTracker::new();

Store::load_from_memory(format, image_bytes, verify, &mut validation_log)
.map(|store| Self::from_store(&store, &validation_log))
}

/// Generate a Store from a format string and stream.
pub fn from_stream(
format: &str,
stream: &mut dyn CAIRead,
verify: bool,
) -> Result<ManifestStore> {
let mut validation_log = DetailedStatusTracker::new();

let manifest_bytes = Store::load_jumbf_from_stream(format, stream)?;
let store = Store::from_jumbf(&manifest_bytes, &mut validation_log)?;
if verify {
// verify store and claims
Store::verify_store(
&store,
&mut ClaimAssetData::Stream(stream, format),
&mut validation_log,
)?;
}
Ok(Self::from_store(&store, &validation_log))
}

#[cfg(feature = "file_io")]
/// Loads a ManifestStore from a file
/// Example:
Expand Down Expand Up @@ -498,4 +519,21 @@ mod tests {
assert_eq!(manifest.issuer().unwrap(), "C2PA Test Signing Cert");
assert!(manifest.time().is_some());
}

#[test]
fn manifest_report_from_stream() {
let image_bytes: &[u8] = include_bytes!("../tests/fixtures/CA.jpg");
let mut stream = std::io::Cursor::new(image_bytes);
let manifest_store = ManifestStore::from_stream("image/jpeg", &mut stream, true).unwrap();
println!("{manifest_store}");

assert!(manifest_store.active_label().is_some());
assert!(manifest_store.get_active().is_some());
assert!(!manifest_store.manifests().is_empty());
assert!(manifest_store.validation_status().is_none());
let manifest = manifest_store.get_active().unwrap();
assert!(!manifest.ingredients().is_empty());
assert_eq!(manifest.issuer().unwrap(), "C2PA Test Signing Cert");
assert!(manifest.time().is_some());
}
}