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