thumbnail.rs (4319B)
1 // Copyright 2022 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use serde::Serialize; 15 16 use crate::{ 17 assertion::{ 18 get_thumbnail_image_type, Assertion, AssertionBase, AssertionData, AssertionDecodeError, 19 }, 20 assertions::labels, 21 error::Result, 22 }; 23 24 /// A Thumbnail assertion 25 #[derive(Serialize)] 26 pub struct Thumbnail { 27 pub data: Vec<u8>, 28 pub label: String, 29 pub content_type: String, 30 } 31 32 impl Thumbnail { 33 pub fn new(label: &str, data: Vec<u8>) -> Self { 34 let image_type = get_thumbnail_image_type(label); 35 let content_type = match image_type.as_str() { 36 "jpeg" | "jpk2" => "image/jpeg", 37 "png" => "image/png", 38 "bmp" => "image/bmp", 39 "gif" => "image/gif", 40 "tiff" => "image/tiff", 41 "ico" => "image/x-icon", 42 "webp" => "image/webp", 43 _ => "application/octet-stream", 44 } 45 .to_string(); 46 47 Thumbnail { 48 data, 49 label: label.to_owned(), 50 content_type, 51 } 52 } 53 } 54 55 impl AssertionBase for Thumbnail { 56 /// returns the base label type for this thumbnail 57 fn label(&self) -> &str { 58 if self.label.starts_with(labels::CLAIM_THUMBNAIL) { 59 labels::CLAIM_THUMBNAIL 60 } else { 61 labels::INGREDIENT_THUMBNAIL 62 } 63 } 64 65 fn to_assertion(&self) -> Result<Assertion> { 66 let data = AssertionData::Binary(self.data.to_owned()); 67 Ok(Assertion::new(&self.label, None, data).set_content_type(&self.content_type)) 68 } 69 70 fn from_assertion(assertion: &Assertion) -> Result<Thumbnail> { 71 match assertion.decode_data() { 72 AssertionData::Binary(data) => Ok(Self { 73 data: data.to_owned(), 74 label: assertion.label(), 75 content_type: assertion.content_type(), 76 }), 77 ad => Err(AssertionDecodeError::from_assertion_unexpected_data_type( 78 assertion, ad, "binary", 79 ) 80 .into()), 81 } 82 } 83 } 84 85 #[cfg(test)] 86 pub mod tests { 87 #![allow(clippy::expect_used)] 88 #![allow(clippy::unwrap_used)] 89 90 use super::*; 91 92 // a binary assertion ('deadbeefadbeadbe') 93 fn some_binary_data() -> Vec<u8> { 94 vec![ 95 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0x0e, 0x0f, 0x0a, 0x0d, 0x0b, 0x0e, 0x0a, 0x0d, 96 0x0b, 0x0e, 97 ] 98 } 99 100 fn thumbnail_test(label: &str, content_type: &str) { 101 let original = Thumbnail::new(label, some_binary_data()); 102 let assertion = original.to_assertion().expect("build_assertion"); 103 assert_eq!(assertion.content_type(), content_type); 104 assert_eq!(assertion.label(), label); 105 let result = Thumbnail::from_assertion(&assertion).expect("from_assertion"); 106 assert_eq!(original.label, result.label); 107 assert_eq!(original.content_type, result.content_type); 108 assert_eq!(original.data, result.data); 109 } 110 111 #[test] 112 fn assertion_thumbnail_valid() { 113 thumbnail_test(labels::JPEG_CLAIM_THUMBNAIL, "image/jpeg"); 114 thumbnail_test(labels::PNG_CLAIM_THUMBNAIL, "image/png"); 115 thumbnail_test(labels::JPEG_INGREDIENT_THUMBNAIL, "image/jpeg"); 116 thumbnail_test(labels::PNG_INGREDIENT_THUMBNAIL, "image/png"); 117 // unrecognized labels will be formatted as octet_streams 118 thumbnail_test("foo", "application/octet-stream"); 119 } 120 121 #[test] 122 fn assertion_thumbnail_invalid_from() { 123 // only current error is if the assertion data is the wrong type, so use JSON 124 let data = AssertionData::Json("foo".to_owned()); 125 let assertion = Assertion::new(labels::JPEG_CLAIM_THUMBNAIL, None, data); 126 let result = Thumbnail::from_assertion(&assertion); 127 assert!(result.is_err()) 128 } 129 }