lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

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 }