lib

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

encode.rs (5011B)


      1 #[cfg(all(not(feature = "std"), test, feature = "json"))]
      2 use alloc::vec;
      3 #[cfg(all(not(feature = "std"), feature = "json"))]
      4 use alloc::{format, string::ToString};
      5 #[cfg(not(feature = "std"))]
      6 use alloc::{string::String, vec::Vec};
      7 
      8 #[cfg(feature = "json")]
      9 use radroots_event::envelope::kind::{KIND_CLASSIFIED_LISTING, is_classified_listing_kind};
     10 use radroots_event::listing::operational::OperationalListing;
     11 
     12 use crate::error::EventEncodeError;
     13 use crate::operational_listing::tags::operational_listing_tags;
     14 #[cfg(feature = "json")]
     15 use crate::operational_listing::tags::operational_listing_tags_full;
     16 #[cfg(feature = "json")]
     17 use radroots_event::wire::Nip01EventWireParts;
     18 
     19 #[cfg(feature = "json")]
     20 const DEFAULT_KIND: u32 = KIND_CLASSIFIED_LISTING;
     21 
     22 pub fn operational_listing_build_tags(
     23     listing: &OperationalListing,
     24 ) -> Result<Vec<Vec<String>>, EventEncodeError> {
     25     operational_listing_tags(listing)
     26 }
     27 
     28 #[cfg(feature = "json")]
     29 pub fn to_wire_parts(
     30     listing: &OperationalListing,
     31 ) -> Result<Nip01EventWireParts, EventEncodeError> {
     32     to_wire_parts_with_kind(listing, DEFAULT_KIND)
     33 }
     34 
     35 #[cfg(feature = "json")]
     36 pub fn to_wire_parts_with_kind(
     37     listing: &OperationalListing,
     38     kind: u32,
     39 ) -> Result<Nip01EventWireParts, EventEncodeError> {
     40     if !is_classified_listing_kind(kind) {
     41         return Err(EventEncodeError::InvalidKind(kind));
     42     }
     43     let tags = operational_listing_tags_full(listing)?;
     44     let content = operational_listing_markdown_content(listing);
     45     Ok(Nip01EventWireParts {
     46         kind,
     47         content,
     48         tags,
     49     })
     50 }
     51 
     52 #[cfg(feature = "json")]
     53 fn operational_listing_markdown_content(listing: &OperationalListing) -> String {
     54     let title = listing.product.title.trim();
     55     let summary = listing
     56         .product
     57         .summary
     58         .as_deref()
     59         .map(str::trim)
     60         .filter(|value| !value.is_empty());
     61 
     62     match (title.is_empty(), summary) {
     63         (false, Some(summary)) => format!("# {title}\n\n{summary}"),
     64         (false, None) => format!("# {title}"),
     65         (true, Some(summary)) => summary.to_string(),
     66         (true, None) => String::new(),
     67     }
     68 }
     69 
     70 #[cfg(all(test, feature = "json"))]
     71 mod tests {
     72     use super::*;
     73     use core::str::FromStr;
     74     use radroots_core::{Currency, Decimal, Money, Quantity, QuantityPrice, Unit};
     75     use radroots_event::{
     76         farm::FarmRef,
     77         id::{DTag, InventoryBinId},
     78         listing::operational::{OperationalListingBin, OperationalListingProduct},
     79     };
     80 
     81     fn decimal(value: &str) -> Decimal {
     82         Decimal::from_str(value).expect("decimal")
     83     }
     84 
     85     fn listing_with(title: &str, summary: Option<&str>) -> OperationalListing {
     86         OperationalListing {
     87             d_tag: DTag::parse("AAAAAAAAAAAAAAAAAAAAAA").expect("d tag"),
     88             published_at: None,
     89             farm: FarmRef {
     90                 pubkey: "a".repeat(64),
     91                 d_tag: "AAAAAAAAAAAAAAAAAAAAAQ".to_string(),
     92             },
     93             product: OperationalListingProduct {
     94                 key: "coffee".to_string(),
     95                 title: title.to_string(),
     96                 category: "produce".to_string(),
     97                 summary: summary.map(ToOwned::to_owned),
     98                 process: None,
     99                 lot: None,
    100                 location: None,
    101                 profile: None,
    102                 year: None,
    103             },
    104             primary_bin_id: InventoryBinId::parse("bin-1").expect("bin id"),
    105             bins: vec![OperationalListingBin {
    106                 bin_id: InventoryBinId::parse("bin-1").expect("bin id"),
    107                 quantity: Quantity::try_new(decimal("1"), Unit::MassG).unwrap(),
    108                 price_per_canonical_unit: QuantityPrice::try_new(
    109                     Money::try_new(decimal("1"), Currency::USD).unwrap(),
    110                     Quantity::try_new(Decimal::ONE, Unit::MassG).unwrap(),
    111                 )
    112                 .unwrap(),
    113                 display_amount: None,
    114                 display_unit: None,
    115                 display_label: None,
    116                 display_price: None,
    117                 display_price_unit: None,
    118             }],
    119             resource_area: None,
    120             plot: None,
    121             discounts: None,
    122             inventory_available: None,
    123             availability: None,
    124             delivery_method: None,
    125             location: None,
    126             images: None,
    127         }
    128     }
    129 
    130     #[test]
    131     fn operational_listing_markdown_content_covers_title_summary_combinations() {
    132         assert_eq!(
    133             operational_listing_markdown_content(&listing_with("Coffee", Some("Washed"))),
    134             "# Coffee\n\nWashed"
    135         );
    136         assert_eq!(
    137             operational_listing_markdown_content(&listing_with("Coffee", None)),
    138             "# Coffee"
    139         );
    140         assert_eq!(
    141             operational_listing_markdown_content(&listing_with(" ", Some("Washed"))),
    142             "Washed"
    143         );
    144         assert_eq!(
    145             operational_listing_markdown_content(&listing_with(" ", None)),
    146             ""
    147         );
    148     }
    149 }