lib

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

decode.rs (4742B)


      1 #![cfg(feature = "serde_json")]
      2 
      3 #[cfg(not(feature = "std"))]
      4 use alloc::{
      5     string::{String, ToString},
      6     vec::Vec,
      7 };
      8 
      9 use radroots_events::{
     10     RadrootsNostrEvent,
     11     farm::RadrootsFarmRef,
     12     kinds::{KIND_FARM, KIND_PLOT},
     13     plot::RadrootsPlot,
     14     tags::TAG_D,
     15 };
     16 
     17 use crate::d_tag::validate_d_tag_tag;
     18 use crate::error::EventParseError;
     19 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent};
     20 
     21 const TAG_A: &str = "a";
     22 const TAG_P: &str = "p";
     23 const DEFAULT_KIND: u32 = KIND_PLOT;
     24 
     25 fn parse_d_tag(tags: &[Vec<String>]) -> Result<String, EventParseError> {
     26     let tag = tags
     27         .iter()
     28         .find(|t| t.first().map(|s| s.as_str()) == Some(TAG_D))
     29         .ok_or(EventParseError::MissingTag(TAG_D))?;
     30     let value = tag
     31         .get(1)
     32         .map(|s| s.to_string())
     33         .ok_or(EventParseError::InvalidTag(TAG_D))?;
     34     if value.trim().is_empty() {
     35         return Err(EventParseError::InvalidTag(TAG_D));
     36     }
     37     validate_d_tag_tag(&value, TAG_D)?;
     38     Ok(value)
     39 }
     40 
     41 fn parse_farm_ref(tags: &[Vec<String>]) -> Result<RadrootsFarmRef, EventParseError> {
     42     let tag = tags
     43         .iter()
     44         .find(|t| t.first().map(|s| s.as_str()) == Some(TAG_A))
     45         .ok_or(EventParseError::MissingTag(TAG_A))?;
     46     let value = tag
     47         .get(1)
     48         .map(|s| s.to_string())
     49         .ok_or(EventParseError::InvalidTag(TAG_A))?;
     50     let mut parts = value.splitn(3, ':');
     51     let kind = parts
     52         .next()
     53         .and_then(|v| v.parse::<u32>().ok())
     54         .ok_or(EventParseError::InvalidTag(TAG_A))?;
     55     if kind != KIND_FARM {
     56         return Err(EventParseError::InvalidTag(TAG_A));
     57     }
     58     let pubkey = parts
     59         .next()
     60         .ok_or(EventParseError::InvalidTag(TAG_A))?
     61         .to_string();
     62     let d_tag = parts
     63         .next()
     64         .ok_or(EventParseError::InvalidTag(TAG_A))?
     65         .to_string();
     66     if pubkey.trim().is_empty() || d_tag.trim().is_empty() {
     67         return Err(EventParseError::InvalidTag(TAG_A));
     68     }
     69     validate_d_tag_tag(&d_tag, TAG_A)?;
     70     Ok(RadrootsFarmRef { pubkey, d_tag })
     71 }
     72 
     73 fn parse_farm_pubkey(tags: &[Vec<String>]) -> Result<String, EventParseError> {
     74     let tag = tags
     75         .iter()
     76         .find(|t| t.first().map(|s| s.as_str()) == Some(TAG_P))
     77         .ok_or(EventParseError::MissingTag(TAG_P))?;
     78     let value = tag
     79         .get(1)
     80         .map(|s| s.to_string())
     81         .ok_or(EventParseError::InvalidTag(TAG_P))?;
     82     if value.trim().is_empty() {
     83         return Err(EventParseError::InvalidTag(TAG_P));
     84     }
     85     Ok(value)
     86 }
     87 
     88 pub fn plot_from_event(
     89     kind: u32,
     90     tags: &[Vec<String>],
     91     content: &str,
     92 ) -> Result<RadrootsPlot, EventParseError> {
     93     if kind != DEFAULT_KIND {
     94         return Err(EventParseError::InvalidKind {
     95             expected: "30350",
     96             got: kind,
     97         });
     98     }
     99     if content.trim().is_empty() {
    100         return Err(EventParseError::InvalidJson("content"));
    101     }
    102     let d_tag = parse_d_tag(tags)?;
    103     let farm_ref = parse_farm_ref(tags)?;
    104     let farm_pubkey = parse_farm_pubkey(tags)?;
    105     let mut plot: RadrootsPlot =
    106         serde_json::from_str(content).map_err(|_| EventParseError::InvalidJson("content"))?;
    107 
    108     if plot.d_tag.trim().is_empty() {
    109         plot.d_tag = d_tag;
    110     } else if plot.d_tag != d_tag {
    111         return Err(EventParseError::InvalidTag(TAG_D));
    112     }
    113 
    114     if plot.farm.pubkey.trim().is_empty() || plot.farm.d_tag.trim().is_empty() {
    115         plot.farm = farm_ref;
    116     } else if plot.farm.pubkey != farm_ref.pubkey || plot.farm.d_tag != farm_ref.d_tag {
    117         return Err(EventParseError::InvalidTag(TAG_A));
    118     }
    119     if plot.farm.pubkey != farm_pubkey {
    120         return Err(EventParseError::InvalidTag(TAG_P));
    121     }
    122 
    123     Ok(plot)
    124 }
    125 
    126 pub fn data_from_event(
    127     id: String,
    128     author: String,
    129     published_at: u32,
    130     kind: u32,
    131     content: String,
    132     tags: Vec<Vec<String>>,
    133 ) -> Result<RadrootsParsedData<RadrootsPlot>, EventParseError> {
    134     let plot = plot_from_event(kind, &tags, &content)?;
    135     Ok(RadrootsParsedData::new(
    136         id,
    137         author,
    138         published_at,
    139         kind,
    140         plot,
    141     ))
    142 }
    143 
    144 pub fn parsed_from_event(
    145     id: String,
    146     author: String,
    147     published_at: u32,
    148     kind: u32,
    149     content: String,
    150     tags: Vec<Vec<String>>,
    151     sig: String,
    152 ) -> Result<RadrootsParsedEvent<RadrootsPlot>, EventParseError> {
    153     let data = data_from_event(
    154         id.clone(),
    155         author.clone(),
    156         published_at,
    157         kind,
    158         content.clone(),
    159         tags.clone(),
    160     )?;
    161     Ok(RadrootsParsedEvent {
    162         event: RadrootsNostrEvent {
    163             id,
    164             author,
    165             created_at: published_at,
    166             kind,
    167             content,
    168             tags,
    169             sig,
    170         },
    171         data,
    172     })
    173 }