Skip to main content

c2pa_ml/
manifest.rs

1//! The manifest payload written into a model, and the reserved metadata keys
2//! it is stored under.
3
4/// The reserved metadata key carrying an embedded C2PA Manifest Store.
5pub(crate) const STORE_KEY: &str = "c2pa.manifest";
6
7/// The reserved metadata key carrying a remote (or side-car) manifest URI.
8pub(crate) const URI_KEY: &str = "c2pa.manifest.uri";
9
10/// What to associate with a model: an embedded Manifest Store, a remote manifest
11/// URI, or both.
12///
13/// Each supported format stores these in the same reserved keys
14/// (`c2pa.manifest` / `c2pa.manifest.uri`) within its native metadata slot.
15#[derive(Debug, Clone, PartialEq, Eq, Default)]
16pub struct ManifestSource {
17    /// URI of the active manifest. The caller fetches the bytes; this crate
18    /// performs no network I/O.
19    pub active_manifest_uri: Option<String>,
20    /// Embedded C2PA Manifest Store bytes (JUMBF).
21    pub manifest_store: Option<Vec<u8>>,
22}
23
24impl ManifestSource {
25    /// Embed a Manifest Store directly in the model.
26    pub fn embedded(manifest_store: Vec<u8>) -> Self {
27        Self {
28            active_manifest_uri: None,
29            manifest_store: Some(manifest_store),
30        }
31    }
32
33    /// Reference a remote (or side-car) manifest by URI.
34    pub fn remote(uri: impl Into<String>) -> Self {
35        Self {
36            active_manifest_uri: Some(uri.into()),
37            manifest_store: None,
38        }
39    }
40
41    /// Embed a Manifest Store and record the active manifest URI.
42    pub fn both(uri: impl Into<String>, manifest_store: Vec<u8>) -> Self {
43        Self {
44            active_manifest_uri: Some(uri.into()),
45            manifest_store: Some(manifest_store),
46        }
47    }
48
49    /// True when neither a store nor a URI is present.
50    pub(crate) fn is_empty(&self) -> bool {
51        self.active_manifest_uri.is_none() && self.manifest_store.is_none()
52    }
53}