lib

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

encode.rs (5400B)


      1 //! Deterministic event encoding boundary.
      2 
      3 #[cfg(all(not(feature = "std"), feature = "json"))]
      4 use alloc::string::String;
      5 use core::fmt;
      6 #[cfg(all(feature = "std", feature = "json"))]
      7 use std::string::String;
      8 
      9 #[cfg(feature = "json")]
     10 use radroots_event::envelope::EventEnvelope;
     11 
     12 // Domain-specific algorithms live behind the canonical encoding namespace.
     13 // Their implementation modules remain crate-private so the public API has one
     14 // stable route for each operation.
     15 pub use crate::error::{EventEncodeError, RadrootsEncodeError};
     16 
     17 macro_rules! encode_domain {
     18     ($name:ident, $source:path) => {
     19         pub mod $name {
     20             pub use $source::*;
     21         }
     22     };
     23 }
     24 
     25 encode_domain!(app_data, crate::app_data::encode);
     26 encode_domain!(article, crate::article::encode);
     27 encode_domain!(calendar, crate::calendar::encode);
     28 pub mod coop {
     29     pub use crate::coop::encode::*;
     30     pub use crate::coop::list_sets::*;
     31 }
     32 encode_domain!(document, crate::document::encode);
     33 encode_domain!(farm_crdt, crate::farm_crdt::encode);
     34 encode_domain!(farm_file, crate::farm_file::encode);
     35 encode_domain!(farm_workspace, crate::farm_workspace::encode);
     36 encode_domain!(file_metadata, crate::file_metadata::encode);
     37 encode_domain!(follow, crate::follow::encode);
     38 encode_domain!(geochat, crate::geochat::encode);
     39 encode_domain!(gift_wrap, crate::gift_wrap::encode);
     40 encode_domain!(group, crate::group::encode);
     41 encode_domain!(http_auth, crate::http_auth::encode);
     42 encode_domain!(list, crate::list::encode);
     43 encode_domain!(list_set, crate::list_set::encode);
     44 encode_domain!(message, crate::message::encode);
     45 encode_domain!(message_file, crate::message_file::encode);
     46 encode_domain!(plot, crate::plot::encode);
     47 encode_domain!(reaction, crate::reaction::encode);
     48 encode_domain!(relay_auth, crate::relay_auth::encode);
     49 #[cfg(feature = "json")]
     50 encode_domain!(relay_document, crate::relay_document::encode);
     51 encode_domain!(report, crate::report::encode);
     52 encode_domain!(repost, crate::repost::encode);
     53 pub mod resource_area {
     54     pub use crate::resource_area::encode::*;
     55     pub use crate::resource_area::list_sets::*;
     56 }
     57 encode_domain!(resource_cap, crate::resource_cap::encode);
     58 encode_domain!(seal, crate::seal::encode);
     59 
     60 pub mod comment {
     61     pub use crate::comment::authored::*;
     62 }
     63 
     64 pub mod deletion {
     65     pub use crate::deletion::authored::*;
     66 }
     67 
     68 pub mod farm {
     69     pub use crate::farm::encode::*;
     70     pub use crate::farm::list_sets::*;
     71 }
     72 
     73 pub mod food_availability {
     74     pub use crate::food_availability::authored::*;
     75 }
     76 
     77 pub mod job {
     78     pub use crate::job::encode::*;
     79 
     80     pub mod feedback {
     81         pub use crate::job::feedback::encode::*;
     82     }
     83     pub mod request {
     84         pub use crate::job::request::encode::*;
     85     }
     86     pub mod result {
     87         pub use crate::job::result::encode::*;
     88     }
     89 }
     90 
     91 pub mod tag_builders {
     92     pub use crate::tag_builders::*;
     93 }
     94 
     95 #[cfg(feature = "knowledge")]
     96 pub mod knowledge {
     97     pub use crate::knowledge::encode::*;
     98 }
     99 
    100 pub mod operational_listing {
    101     pub use crate::operational_listing::encode::*;
    102     pub use crate::operational_listing::tags::*;
    103 }
    104 
    105 pub mod order {
    106     #[cfg(feature = "json")]
    107     pub use crate::order::encode::*;
    108     pub use crate::order::tags::*;
    109 }
    110 
    111 pub mod post {
    112     pub use crate::post::authored::*;
    113 }
    114 
    115 #[cfg(feature = "json")]
    116 pub mod profile {
    117     pub use crate::profile::authored::*;
    118 }
    119 
    120 pub mod reply {
    121     pub use crate::reply::authored::*;
    122 }
    123 
    124 #[cfg(feature = "json")]
    125 pub mod rhi {
    126     pub use crate::rhi::{
    127         RADROOTS_RHI_EVIDENCE_ATTESTATION_CONTRACT_ID,
    128         RADROOTS_RHI_EVIDENCE_ATTESTATION_MAXIMUM_BYTES, RadrootsRhiEvidenceAttestationError,
    129         RadrootsRhiEvidenceAttestationV1, rhi_evidence_attestation_event_build,
    130         rhi_evidence_attestation_event_build_with_extra_tags,
    131     };
    132 }
    133 
    134 #[cfg(feature = "json")]
    135 pub mod trade {
    136     pub use crate::trade::{
    137         RadrootsTradeMutationError, trade_mutation_event_build,
    138         trade_mutation_event_build_with_extra_tags, trade_mutation_tags,
    139     };
    140 }
    141 
    142 /// A failure while encoding an event.
    143 #[non_exhaustive]
    144 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    145 pub enum EncodeError {
    146     /// The event could not be represented as canonical compact JSON.
    147     Json,
    148 }
    149 
    150 impl EncodeError {
    151     /// Returns a stable machine-readable error code.
    152     #[must_use]
    153     pub const fn code(self) -> &'static str {
    154         match self {
    155             Self::Json => "json",
    156         }
    157     }
    158 }
    159 
    160 impl fmt::Display for EncodeError {
    161     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
    162         formatter.write_str("failed to encode event JSON")
    163     }
    164 }
    165 
    166 #[cfg(feature = "std")]
    167 impl std::error::Error for EncodeError {}
    168 
    169 /// Encodes an event as deterministic compact NIP-01 JSON.
    170 ///
    171 /// This operation preserves the supplied envelope; it does not imply that the
    172 /// identifier, signature, or contract has been verified.
    173 ///
    174 /// ```no_run
    175 /// # #[cfg(feature = "json")]
    176 /// # {
    177 /// # let raw_json = r#"{"id":"00","pubkey":"00","created_at":0,"kind":1,"tags":[],"content":"","sig":"00"}"#;
    178 /// let raw = radroots_event_codec::decode::event(raw_json)?;
    179 /// let encoded = radroots_event_codec::encode::event(raw.event())?;
    180 /// # let _ = encoded;
    181 /// # }
    182 /// # Ok::<(), Box<dyn std::error::Error>>(())
    183 /// ```
    184 #[cfg(feature = "json")]
    185 pub fn event(event: &EventEnvelope) -> Result<String, EncodeError> {
    186     serde_json::to_string(&event.to_nip01_wire()).map_err(|_| EncodeError::Json)
    187 }