farm_file.rs (4850B)
1 #![forbid(unsafe_code)] 2 3 use crate::envelope::kind::KIND_FARM_FILE_METADATA as KIND_FARM_FILE_METADATA_EVENT; 4 use crate::farm::crdt::FarmCrdtDocumentKind; 5 use crate::farm::workspace::FarmWorkspaceRef; 6 7 #[cfg(not(feature = "std"))] 8 use alloc::{string::String, vec::Vec}; 9 10 pub const KIND_FARM_FILE_METADATA: u32 = KIND_FARM_FILE_METADATA_EVENT; 11 12 #[cfg_attr( 13 any(feature = "serde", test), 14 derive(serde::Serialize, serde::Deserialize) 15 )] 16 #[derive(Clone, Debug, PartialEq, Eq)] 17 pub struct FarmFileMetadata { 18 pub d_tag: String, 19 pub workspace: FarmWorkspaceRef, 20 pub farm_group_id: String, 21 pub owner_document_id: String, 22 pub owner_document_kind: FarmCrdtDocumentKind, 23 pub caption: Option<String>, 24 pub url: String, 25 pub mime_type: String, 26 pub sha256: String, 27 pub original_sha256: Option<String>, 28 pub size_bytes: Option<u64>, 29 pub dimensions: Option<FarmFileDimensions>, 30 pub blurhash: Option<String>, 31 pub thumb: Option<FarmFileSource>, 32 pub image: Option<FarmFileSource>, 33 pub alt: Option<String>, 34 pub fallbacks: Vec<String>, 35 } 36 37 #[cfg_attr( 38 any(feature = "serde", test), 39 derive(serde::Serialize, serde::Deserialize) 40 )] 41 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 42 pub struct FarmFileDimensions { 43 pub w: u32, 44 pub h: u32, 45 } 46 47 #[cfg_attr( 48 any(feature = "serde", test), 49 derive(serde::Serialize, serde::Deserialize) 50 )] 51 #[derive(Clone, Debug, PartialEq, Eq)] 52 pub struct FarmFileSource { 53 pub url: String, 54 pub mime_type: Option<String>, 55 pub dimensions: Option<FarmFileDimensions>, 56 } 57 58 #[cfg(all(test, feature = "serde"))] 59 #[cfg_attr(coverage_nightly, coverage(off))] 60 mod tests { 61 use super::*; 62 63 #[test] 64 fn file_metadata_kind_uses_nip94_file_metadata_kind() { 65 assert_eq!(KIND_FARM_FILE_METADATA, 1063); 66 } 67 68 #[test] 69 fn file_metadata_remains_separate_from_message_file_model() { 70 let metadata = sample_file_metadata(); 71 72 assert_eq!(metadata.d_tag, "EFGHIJKLMNOPQRSTUVWXYZ"); 73 assert_eq!(metadata.owner_document_id, "DEFGHIJKLMNOPQRSTUVWXY"); 74 assert_eq!(metadata.owner_document_kind, FarmCrdtDocumentKind::FarmTask); 75 assert_eq!( 76 metadata.caption.as_deref(), 77 Some("Tomatoes harvested from Patch Y.") 78 ); 79 assert_eq!(metadata.mime_type, "image/jpeg"); 80 assert_eq!( 81 metadata.dimensions, 82 Some(FarmFileDimensions { w: 1600, h: 1200 }) 83 ); 84 assert_eq!(metadata.fallbacks.len(), 1); 85 } 86 87 #[test] 88 fn file_metadata_serializes_stable_content_shape() { 89 let value = serde_json::to_value(sample_file_metadata()).unwrap(); 90 91 assert_eq!(value["workspace"]["d_tag"], "ABCDEFGHIJKLMNOPQRSTUV"); 92 assert_eq!(value["farm_group_id"], "BCDEFGHIJKLMNOPQRSTUVW"); 93 assert_eq!(value["owner_document_kind"], "FarmTask"); 94 assert_eq!(value["caption"], "Tomatoes harvested from Patch Y."); 95 assert_eq!(value["mime_type"], "image/jpeg"); 96 assert_eq!( 97 value["sha256"], 98 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 99 ); 100 assert_eq!(value["dimensions"]["w"], 1600); 101 assert_eq!(value["dimensions"]["h"], 1200); 102 } 103 104 fn sample_file_metadata() -> FarmFileMetadata { 105 FarmFileMetadata { 106 d_tag: "EFGHIJKLMNOPQRSTUVWXYZ".to_string(), 107 workspace: FarmWorkspaceRef { 108 pubkey: "workspace_pubkey".to_string(), 109 d_tag: "ABCDEFGHIJKLMNOPQRSTUV".to_string(), 110 }, 111 farm_group_id: "BCDEFGHIJKLMNOPQRSTUVW".to_string(), 112 owner_document_id: "DEFGHIJKLMNOPQRSTUVWXY".to_string(), 113 owner_document_kind: FarmCrdtDocumentKind::FarmTask, 114 caption: Some("Tomatoes harvested from Patch Y.".to_string()), 115 url: "https://media.example.invalid/blob/sha256".to_string(), 116 mime_type: "image/jpeg".to_string(), 117 sha256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), 118 original_sha256: Some( 119 "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789".to_string(), 120 ), 121 size_bytes: Some(123_456), 122 dimensions: Some(FarmFileDimensions { w: 1600, h: 1200 }), 123 blurhash: Some("LEHV6nWB2yk8pyo0adR*.7kCMdnj".to_string()), 124 thumb: Some(FarmFileSource { 125 url: "https://media.example.invalid/thumb/sha256".to_string(), 126 mime_type: Some("image/jpeg".to_string()), 127 dimensions: Some(FarmFileDimensions { w: 320, h: 240 }), 128 }), 129 image: None, 130 alt: Some("Harvested tomatoes in a crate".to_string()), 131 fallbacks: vec!["https://fallback.example.invalid/blob/sha256".to_string()], 132 } 133 } 134 }