use crate::error::Error;
use crate::extract::extract_manifest;
use c2pa_structured_text::{codec, DATA_URI_PREFIX};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ManifestSource {
Url(String),
Embedded(Vec<u8>),
}
pub fn extract_manifest_source(text: &str) -> Result<ManifestSource, Error> {
let reference = extract_manifest(text)?.reference;
match reference.strip_prefix(DATA_URI_PREFIX) {
Some(b64) => {
let bytes = codec::decode(b64).map_err(|e| Error::MalformedReference(e.to_string()))?;
Ok(ManifestSource::Embedded(bytes))
}
None => Ok(ManifestSource::Url(reference)),
}
}
#[cfg(feature = "c2pa")]
pub fn validate(vtt: &str, manifest_store: &[u8]) -> Result<c2pa::Reader, c2pa::Error> {
use std::io::Cursor;
c2pa::Reader::from_context(c2pa::Context::new()).with_manifest_data_and_stream(
manifest_store,
"text/vtt",
Cursor::new(vtt.as_bytes()),
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::embed::{embed_manifest, ManifestRef};
#[test]
fn resolves_url() {
let vtt =
embed_manifest("WEBVTT\n", ManifestRef::Url("https://example.com/m.c2pa")).unwrap();
assert_eq!(
extract_manifest_source(&vtt).unwrap(),
ManifestSource::Url("https://example.com/m.c2pa".to_string())
);
}
#[test]
fn resolves_embedded_data_uri() {
let store = b"\x00\x01store-bytes\xff";
let vtt = embed_manifest("WEBVTT\n", ManifestRef::Embedded(store)).unwrap();
assert_eq!(
extract_manifest_source(&vtt).unwrap(),
ManifestSource::Embedded(store.to_vec())
);
}
#[test]
fn malformed_data_uri_is_rejected() {
let vtt = "WEBVTT\n\nNOTE -----BEGIN C2PA MANIFEST----- data:application/c2pa;base64,@@@ -----END C2PA MANIFEST-----\n";
assert!(matches!(
extract_manifest_source(vtt),
Err(Error::MalformedReference(_))
));
}
}