encode.rs (4151B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{format, string::String, vec::Vec}; 3 4 #[cfg(feature = "json")] 5 use radroots_event::farm::crdt::KIND_FARM_CRDT_CHANGE; 6 use radroots_event::{ 7 farm::crdt::{FarmCrdtChange, RADROOTS_FARM_CRDT_CHANGE_SCHEMA, RADROOTS_FARM_CRDT_TAG}, 8 farm::workspace::KIND_FARM_WORKSPACE_MANIFEST, 9 tag::name::{TAG_A, TAG_D, TAG_H, TAG_P, TAG_T}, 10 }; 11 12 use crate::d_tag::validate_d_tag; 13 use crate::error::EventEncodeError; 14 use crate::field_helpers::{ 15 push_optional_tag, push_tag, validate_non_empty_base64url, validate_non_empty_field, 16 }; 17 #[cfg(feature = "json")] 18 use radroots_event::wire::Nip01EventWireParts; 19 20 pub fn farm_crdt_change_build_tags( 21 change: &FarmCrdtChange, 22 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 23 farm_crdt_change_build_tags_with_author(change, None) 24 } 25 26 pub fn farm_crdt_change_build_tags_with_author( 27 change: &FarmCrdtChange, 28 author_pubkey: Option<&str>, 29 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 30 validate_change(change)?; 31 if let Some(author_pubkey) = author_pubkey { 32 validate_non_empty_field(author_pubkey, "author_pubkey")?; 33 } 34 let workspace = format!( 35 "{KIND_FARM_WORKSPACE_MANIFEST}:{}:{}", 36 change.workspace.pubkey, change.workspace.d_tag 37 ); 38 let mut tags = Vec::new(); 39 push_tag(&mut tags, TAG_H, change.farm_group_id.as_str()); 40 push_tag(&mut tags, TAG_D, change.document_id.as_str()); 41 push_tag(&mut tags, TAG_A, workspace); 42 push_optional_tag(&mut tags, TAG_P, author_pubkey); 43 push_tag(&mut tags, TAG_T, RADROOTS_FARM_CRDT_TAG); 44 Ok(tags) 45 } 46 47 #[cfg(feature = "json")] 48 pub fn to_wire_parts(change: &FarmCrdtChange) -> Result<Nip01EventWireParts, EventEncodeError> { 49 to_wire_parts_with_kind(change, KIND_FARM_CRDT_CHANGE) 50 } 51 52 #[cfg(feature = "json")] 53 pub fn to_wire_parts_with_author( 54 change: &FarmCrdtChange, 55 author_pubkey: &str, 56 ) -> Result<Nip01EventWireParts, EventEncodeError> { 57 to_wire_parts_with_kind_and_author(change, KIND_FARM_CRDT_CHANGE, Some(author_pubkey)) 58 } 59 60 #[cfg(feature = "json")] 61 pub fn to_wire_parts_with_kind( 62 change: &FarmCrdtChange, 63 kind: u32, 64 ) -> Result<Nip01EventWireParts, EventEncodeError> { 65 to_wire_parts_with_kind_and_author(change, kind, None) 66 } 67 68 #[cfg(feature = "json")] 69 pub fn to_wire_parts_with_kind_and_author( 70 change: &FarmCrdtChange, 71 kind: u32, 72 author_pubkey: Option<&str>, 73 ) -> Result<Nip01EventWireParts, EventEncodeError> { 74 if kind != KIND_FARM_CRDT_CHANGE { 75 return Err(EventEncodeError::InvalidKind(kind)); 76 } 77 let tags = farm_crdt_change_build_tags_with_author(change, author_pubkey)?; 78 let content = serde_json::to_string(change).map_err(|_| EventEncodeError::Json)?; 79 Ok(Nip01EventWireParts { 80 kind, 81 content, 82 tags, 83 }) 84 } 85 86 pub(crate) fn validate_change(change: &FarmCrdtChange) -> Result<(), EventEncodeError> { 87 if change.schema != RADROOTS_FARM_CRDT_CHANGE_SCHEMA { 88 return Err(EventEncodeError::InvalidField("schema")); 89 } 90 validate_non_empty_field(&change.farm_group_id, "farm_group_id")?; 91 validate_d_tag(&change.document_id, "document_id")?; 92 validate_non_empty_field(&change.workspace.pubkey, "workspace.pubkey")?; 93 validate_d_tag(&change.workspace.d_tag, "workspace.d_tag")?; 94 validate_non_empty_field(&change.actor_id, "actor_id")?; 95 validate_non_empty_field(&change.change_hash, "change_hash")?; 96 for dependency in &change.dependencies { 97 validate_non_empty_field(dependency, "dependencies")?; 98 } 99 validate_non_empty_base64url(&change.encoded_change, "encoded_change")?; 100 if change.business_time_ms == 0 { 101 return Err(EventEncodeError::InvalidField("business_time_ms")); 102 } 103 if let Some(version) = change.crdt_backend_version.as_deref() { 104 validate_non_empty_field(version, "crdt_backend_version")?; 105 } 106 if let Some(member_id) = change.author_member_id.as_deref() { 107 validate_non_empty_field(member_id, "author_member_id")?; 108 } 109 if let Some(app_version) = change.app_version.as_deref() { 110 validate_non_empty_field(app_version, "app_version")?; 111 } 112 Ok(()) 113 }