decode.rs (4714B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{string::String, vec::Vec}; 3 4 use radroots_event::{ 5 envelope::kind::KIND_FARM, 6 farm::workspace::{ 7 FarmWorkspaceManifest, KIND_FARM_WORKSPACE_MANIFEST, RADROOTS_FARM_WORKSPACE_TAG, 8 }, 9 tag::name::{TAG_A, TAG_D, TAG_H, TAG_P, TAG_T}, 10 }; 11 12 use crate::d_tag::validate_d_tag_tag; 13 use crate::error::EventParseError; 14 use crate::farm_workspace::encode::validate_manifest; 15 use crate::field_helpers::{ 16 optional_tag_value, parse_address_tag_with_kind, required_tag_value, tag_values, 17 }; 18 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent}; 19 20 const EXPECTED_KIND: &str = "30078"; 21 22 pub fn farm_workspace_from_event( 23 kind: u32, 24 tags: &[Vec<String>], 25 content: &str, 26 ) -> Result<FarmWorkspaceManifest, EventParseError> { 27 if kind != KIND_FARM_WORKSPACE_MANIFEST { 28 return Err(EventParseError::InvalidKind { 29 expected: EXPECTED_KIND, 30 got: kind, 31 }); 32 } 33 if content.trim().is_empty() { 34 return Err(EventParseError::InvalidJson("content")); 35 } 36 let d_tag = required_tag_value(tags, TAG_D)?; 37 validate_d_tag_tag(&d_tag, TAG_D)?; 38 let farm_group_id = required_tag_value(tags, TAG_H)?; 39 let manifest: FarmWorkspaceManifest = 40 serde_json::from_str(content).map_err(|_| EventParseError::InvalidJson("content"))?; 41 validate_manifest(&manifest).map_err(encode_error_to_parse_error)?; 42 43 if manifest.d_tag != d_tag { 44 return Err(EventParseError::InvalidTag(TAG_D)); 45 } 46 if manifest.farm_group_id != farm_group_id { 47 return Err(EventParseError::InvalidTag(TAG_H)); 48 } 49 if let Some(owner_pubkey) = optional_tag_value(tags, TAG_P)? 50 && owner_pubkey != manifest.owner_pubkey 51 { 52 return Err(EventParseError::InvalidTag(TAG_P)); 53 } 54 let marker_tags = tag_values(tags, TAG_T)?; 55 if !marker_tags 56 .iter() 57 .any(|value| value == RADROOTS_FARM_WORKSPACE_TAG) 58 { 59 return Err(EventParseError::MissingTag(TAG_T)); 60 } 61 if let Some(farm) = manifest.farm.as_ref() { 62 let farm_address = optional_tag_value(tags, TAG_A)?; 63 if let Some(value) = farm_address { 64 let address = parse_address_tag_with_kind(&value, KIND_FARM, TAG_A)?; 65 if address.pubkey != farm.pubkey || address.d_tag != farm.d_tag { 66 return Err(EventParseError::InvalidTag(TAG_A)); 67 } 68 } 69 } 70 71 Ok(manifest) 72 } 73 74 pub fn data_from_event( 75 id: String, 76 author: String, 77 published_at: u64, 78 kind: u32, 79 content: String, 80 tags: Vec<Vec<String>>, 81 ) -> Result<RadrootsParsedData<FarmWorkspaceManifest>, EventParseError> { 82 let manifest = farm_workspace_from_event(kind, &tags, &content)?; 83 Ok(RadrootsParsedData::new( 84 id, 85 author, 86 published_at, 87 kind, 88 manifest, 89 )) 90 } 91 92 pub fn parsed_from_event( 93 id: String, 94 author: String, 95 published_at: u64, 96 kind: u32, 97 content: String, 98 tags: Vec<Vec<String>>, 99 sig: String, 100 ) -> Result<RadrootsParsedEvent<FarmWorkspaceManifest>, EventParseError> { 101 let data = data_from_event( 102 id.clone(), 103 author.clone(), 104 published_at, 105 kind, 106 content.clone(), 107 tags.clone(), 108 )?; 109 RadrootsParsedEvent::from_event_parts(id, author, published_at, kind, content, tags, sig, data) 110 } 111 112 fn encode_error_to_parse_error(error: crate::error::EventEncodeError) -> EventParseError { 113 match error { 114 crate::error::EventEncodeError::InvalidKind(kind) => EventParseError::InvalidKind { 115 expected: EXPECTED_KIND, 116 got: kind, 117 }, 118 crate::error::EventEncodeError::EmptyRequiredField(field) 119 | crate::error::EventEncodeError::InvalidField(field) => match field { 120 "d_tag" | "farm.d_tag" => EventParseError::InvalidTag(TAG_D), 121 "farm_group_id" => EventParseError::InvalidTag(TAG_H), 122 "owner_pubkey" => EventParseError::InvalidTag(TAG_P), 123 _ => EventParseError::InvalidJson(field), 124 }, 125 crate::error::EventEncodeError::Json => EventParseError::InvalidJson("content"), 126 } 127 } 128 129 #[cfg(test)] 130 mod tests { 131 use super::*; 132 use crate::error::EventEncodeError; 133 134 #[test] 135 fn encode_error_mapper_covers_kind_and_json_edges() { 136 assert!(matches!( 137 encode_error_to_parse_error(EventEncodeError::InvalidKind(1)), 138 EventParseError::InvalidKind { 139 expected: EXPECTED_KIND, 140 got: 1 141 } 142 )); 143 assert!(matches!( 144 encode_error_to_parse_error(EventEncodeError::Json), 145 EventParseError::InvalidJson("content") 146 )); 147 } 148 }