use crate::error::Error;
use crate::record::{parse_records, WarcRecord};
pub fn read_manifest(data: &[u8]) -> Result<Vec<u8>, Error> {
let records = parse_records(data)?;
let manifest = records
.iter()
.rev()
.find(|r| r.is_c2pa_manifest())
.ok_or(Error::NotFound)?;
Ok(manifest.body.clone())
}
pub fn read_records(data: &[u8]) -> Result<Vec<WarcRecord>, Error> {
parse_records(data)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::record::build_record;
#[test]
fn read_manifest_from_warc() {
let r1 = build_record(
"response",
"text/html",
"urn:uuid:aaa",
Some("https://example.com/"),
b"<html></html>",
);
let manifest_bytes = b"\x00\x01\x02\x03";
let r2 = build_record(
"c2paprovenance",
"application/c2pa",
"urn:uuid:bbb",
None,
manifest_bytes,
);
let mut warc = Vec::new();
warc.extend_from_slice(&r1);
warc.extend_from_slice(&r2);
let result = read_manifest(&warc).unwrap();
assert_eq!(result, manifest_bytes);
}
#[test]
fn uses_last_manifest() {
let r1 = build_record(
"c2paprovenance",
"application/c2pa",
"urn:uuid:old",
None,
b"old",
);
let r2 = build_record(
"response",
"text/html",
"urn:uuid:mid",
Some("https://example.com/"),
b"<html></html>",
);
let r3 = build_record(
"c2paprovenance",
"application/c2pa",
"urn:uuid:new",
None,
b"new",
);
let mut warc = Vec::new();
warc.extend_from_slice(&r1);
warc.extend_from_slice(&r2);
warc.extend_from_slice(&r3);
let result = read_manifest(&warc).unwrap();
assert_eq!(result, b"new");
}
#[test]
fn no_manifest() {
let r1 = build_record(
"response",
"text/html",
"urn:uuid:aaa",
Some("https://example.com/"),
b"<html></html>",
);
assert!(matches!(read_manifest(&r1), Err(Error::NotFound)));
}
}