lib

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

encode.rs (4778B)


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