use serde::Serialize;
use crate::{
assertion::{Assertion, AssertionBase, AssertionData},
assertions::labels,
error::Result,
};
#[derive(Serialize)]
pub struct EmbeddedData {
pub label: String,
pub content_type: String,
pub data: Vec<u8>,
}
impl EmbeddedData {
pub const LABEL: &'static str = labels::EMBEDDED_DATA;
pub fn new<L, C, D>(label: L, content_type: C, data: D) -> Self
where
L: Into<String>,
C: Into<String>,
D: Into<Vec<u8>>,
{
Self {
data: data.into(),
label: label.into(),
content_type: content_type.into(),
}
}
}
impl AssertionBase for EmbeddedData {
fn label(&self) -> &str {
self.label.as_str()
}
fn to_assertion(&self) -> Result<Assertion> {
let data = AssertionData::Binary(self.data.to_owned());
Ok(Assertion::new(&self.label, None, data).set_content_type(&self.content_type))
}
fn from_assertion(assertion: &Assertion) -> Result<Self> {
assertion.try_into()
}
}
impl TryFrom<Assertion> for EmbeddedData {
type Error = crate::Error;
fn try_from(assertion: Assertion) -> Result<Self> {
match crate::assertion::Assertion::binary_deconstruct(assertion) {
Ok((label, _version, content_type, data)) => Ok(Self {
data,
label,
content_type,
}),
Err(err) => Err(err),
}
}
}
impl TryFrom<&Assertion> for EmbeddedData {
type Error = crate::Error;
fn try_from(assertion: &Assertion) -> Result<Self> {
assertion.clone().try_into()
}
}
#[cfg(test)]
pub mod tests {
#![allow(clippy::expect_used)]
#![allow(clippy::unwrap_used)]
use super::*;
fn some_binary_data() -> Vec<u8> {
vec![
0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0x0e, 0x0f, 0x0a, 0x0d, 0x0b, 0x0e, 0x0a, 0x0d,
0x0b, 0x0e,
]
}
fn embedded_data_test(label: &str, content_type: &str) {
let original = EmbeddedData::new(label, content_type, some_binary_data());
let assertion = original.to_assertion().expect("build_assertion");
assert_eq!(assertion.content_type(), content_type);
assert_eq!(assertion.label(), label);
let result = EmbeddedData::from_assertion(&assertion).expect("from_assertion");
assert_eq!(original.label, result.label);
assert_eq!(original.content_type, result.content_type);
assert_eq!(original.data, result.data);
}
#[test]
fn assertion_embedded_data_valid() {
embedded_data_test(labels::JPEG_CLAIM_THUMBNAIL, "image/jpeg");
embedded_data_test(labels::PNG_CLAIM_THUMBNAIL, "image/png");
embedded_data_test(labels::JPEG_INGREDIENT_THUMBNAIL, "image/jpeg");
embedded_data_test(labels::PNG_INGREDIENT_THUMBNAIL, "image/png");
embedded_data_test("foo", "application/octet-stream");
}
#[test]
fn assertion_embedded_data_invalid_from() {
let data = AssertionData::Json("foo".to_owned());
let assertion = Assertion::new(labels::JPEG_CLAIM_THUMBNAIL, None, data);
let result = EmbeddedData::from_assertion(&assertion);
assert!(result.is_err())
}
#[test]
fn assertion_embedded_data_with_format() {
let original = EmbeddedData::new(EmbeddedData::LABEL, "image/png", some_binary_data());
let assertion = original.to_assertion().expect("build_assertion");
assert_eq!(assertion.content_type(), "image/png");
assert_eq!(assertion.label(), EmbeddedData::LABEL);
let result = EmbeddedData::from_assertion(&assertion).expect("from_assertion");
assert_eq!(original.label, result.label);
assert_eq!(original.content_type, result.content_type);
assert_eq!(original.data, result.data);
}
}