commit 2ba7c8bbc1302fca7be1a88442617caf24cd0afe
parent c884f30e3d4000171b5fabefbc4b73b38b9c1338
Author: nick <nickyboy04@icloud.com>
Date: Mon, 10 Jun 2024 10:57:19 -0400
Implement `Debug` w/ detailed manifest for `Reader` (#473)
* Add `Store` field to `ManifestStore`
* Serializable `Reader` + detailed manifest from `Debug`
* Fix clippy lints
* Remove `Serialize` from `Reader`
* Require `UnwindSafe` + `RefUnwindSafe` on `TrustHandlerConfig` trait
Diffstat:
3 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/sdk/src/manifest_store.rs b/sdk/src/manifest_store.rs
@@ -45,6 +45,9 @@ pub struct ManifestStore {
#[serde(skip_serializing_if = "Option::is_none")]
/// ValidationStatus generated when loading the ManifestStore from an asset
validation_status: Option<Vec<ValidationStatus>>,
+ #[serde(skip)]
+ /// The internal store representing the manifest store
+ store: Store,
}
impl ManifestStore {
@@ -54,6 +57,7 @@ impl ManifestStore {
active_manifest: None,
manifests: HashMap::<String, Manifest>::new(),
validation_status: None,
+ store: Store::new(),
}
}
@@ -112,7 +116,7 @@ impl ManifestStore {
}
/// creates a ManifestStore from a Store with validation
- pub(crate) fn from_store(store: &Store, validation_log: &impl StatusTracker) -> ManifestStore {
+ pub(crate) fn from_store(store: Store, validation_log: &impl StatusTracker) -> ManifestStore {
Self::from_store_impl(
store,
validation_log,
@@ -124,7 +128,7 @@ impl ManifestStore {
/// creates a ManifestStore from a Store writing resources to resource_path
#[cfg(feature = "file_io")]
pub(crate) fn from_store_with_resources(
- store: &Store,
+ store: Store,
validation_log: &impl StatusTracker,
resource_path: &Path,
) -> ManifestStore {
@@ -133,15 +137,17 @@ impl ManifestStore {
// internal implementation of from_store
fn from_store_impl(
- store: &Store,
+ store: Store,
validation_log: &impl StatusTracker,
#[cfg(feature = "file_io")] resource_path: Option<&Path>,
) -> ManifestStore {
- let mut statuses = status_for_store(store, validation_log);
+ let mut statuses = status_for_store(&store, validation_log);
let mut manifest_store = ManifestStore::new();
manifest_store.active_manifest = store.provenance_label();
+ manifest_store.store = store;
+ let store = &manifest_store.store;
for claim in store.claims() {
let manifest_label = claim.label();
#[cfg(feature = "file_io")]
@@ -167,13 +173,17 @@ impl ManifestStore {
manifest_store
}
+ pub(crate) fn store(&self) -> &Store {
+ &self.store
+ }
+
/// Creates a new Manifest Store from a Manifest
#[allow(dead_code)]
pub fn from_manifest(manifest: &Manifest) -> Result<Self> {
use crate::status_tracker::OneShotStatusTracker;
let store = manifest.to_store()?;
Ok(Self::from_store_impl(
- &store,
+ store,
&OneShotStatusTracker::new(),
#[cfg(feature = "file_io")]
manifest.resources().base_path(),
@@ -186,7 +196,7 @@ impl 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))
+ .map(|store| Self::from_store(store, &validation_log))
}
/// Generate a Store from a format string and stream.
@@ -221,7 +231,7 @@ impl ManifestStore {
.await?;
}
}
- Ok(Self::from_store(&store, &validation_log))
+ Ok(Self::from_store(store, &validation_log))
}
#[cfg(feature = "file_io")]
@@ -242,7 +252,7 @@ impl ManifestStore {
let mut validation_log = DetailedStatusTracker::new();
let store = Store::load_from_asset(path.as_ref(), true, &mut validation_log)?;
- Ok(Self::from_store(&store, &validation_log))
+ Ok(Self::from_store(store, &validation_log))
}
#[cfg(feature = "file_io")]
@@ -270,7 +280,7 @@ impl ManifestStore {
let store = Store::load_from_asset(path.as_ref(), true, &mut validation_log)?;
Ok(Self::from_store_with_resources(
- &store,
+ store,
&validation_log,
resource_path.as_ref(),
))
@@ -287,7 +297,7 @@ impl ManifestStore {
Store::load_from_memory_async(format, image_bytes, verify, &mut validation_log)
.await
- .map(|store| Self::from_store(&store, &validation_log))
+ .map(|store| Self::from_store(store, &validation_log))
}
/// Loads a ManifestStore from an init segment and fragment. This
@@ -309,7 +319,7 @@ impl ManifestStore {
&mut validation_log,
)
.await
- .map(|store| Self::from_store(&store, &validation_log))
+ .map(|store| Self::from_store(store, &validation_log))
}
/// Asynchronously loads a manifest from a buffer holding a binary manifest (.c2pa) and validates against an asset buffer
@@ -348,7 +358,7 @@ impl ManifestStore {
)
.await?;
- Ok(Self::from_store(&store, &validation_log))
+ Ok(Self::from_store(store, &validation_log))
}
/// Synchronously loads a manifest from a buffer holding a binary manifest (.c2pa) and validates against an asset buffer
@@ -384,7 +394,7 @@ impl ManifestStore {
&mut validation_log,
)?;
- Ok(Self::from_store(&store, &validation_log))
+ Ok(Self::from_store(store, &validation_log))
}
}
@@ -463,7 +473,7 @@ mod tests {
fn manifest_report() {
let store = create_test_store().expect("creating test store");
- let manifest_store = ManifestStore::from_store(&store, &OneShotStatusTracker::new());
+ let manifest_store = ManifestStore::from_store(store, &OneShotStatusTracker::new());
assert!(manifest_store.active_manifest.is_some());
assert!(!manifest_store.manifests.is_empty());
let manifest = manifest_store.get_active().unwrap();
diff --git a/sdk/src/reader.rs b/sdk/src/reader.rs
@@ -25,11 +25,10 @@ use crate::error::Error;
use crate::{
claim::ClaimAssetData, error::Result, manifest_store::ManifestStore,
settings::get_settings_value, status_tracker::DetailedStatusTracker, store::Store,
- validation_status::ValidationStatus, Manifest,
+ validation_status::ValidationStatus, Manifest, ManifestStoreReport,
};
/// A reader for the manifest store.
-#[derive(Debug)]
pub struct Reader {
pub(crate) manifest_store: ManifestStore,
}
@@ -150,7 +149,7 @@ impl Reader {
}
Ok(Reader {
- manifest_store: ManifestStore::from_store(&store, &validation_log),
+ manifest_store: ManifestStore::from_store(store, &validation_log),
})
}
@@ -235,3 +234,11 @@ impl std::fmt::Display for Reader {
f.write_str(self.json().as_str())
}
}
+
+impl std::fmt::Debug for Reader {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let report = ManifestStoreReport::from_store(self.manifest_store.store())
+ .map_err(|_| std::fmt::Error)?;
+ f.write_str(&report.to_string())
+ }
+}
diff --git a/sdk/src/trust_handler.rs b/sdk/src/trust_handler.rs
@@ -14,6 +14,7 @@
use std::{
collections::HashSet,
io::{read_to_string, Cursor, Read},
+ panic::{RefUnwindSafe, UnwindSafe},
str::FromStr,
};
@@ -27,7 +28,10 @@ pub(crate) static OCSP_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .9)
pub(crate) static DOCUMENT_SIGNING_OID: Oid<'static> = oid!(1.3.6 .1 .5 .5 .7 .3 .36);
// Trait for supply configuration and handling of trust lists and EKU configuration store
-pub(crate) trait TrustHandlerConfig: Sync + Send {
+//
+// `RefUnwindSafe` + `UnwindSafe` were added to ensure `Store` is unwind safe and to preserve
+// backwards compatbility.
+pub(crate) trait TrustHandlerConfig: RefUnwindSafe + UnwindSafe + Sync + Send {
fn new() -> Self
where
Self: Sized;
@@ -122,6 +126,7 @@ pub(crate) fn load_trust_from_data(trust_data: &[u8]) -> Result<Vec<Vec<u8>>> {
// Pass through trust for the case of claim signer usage since it has known trust with context
// configured to all email protection, timestamping, ocsp signing and document signing
+#[derive(Debug)]
pub(crate) struct TrustPassThrough {
allowed_cert_set: HashSet<String>,
config_store: Vec<u8>,