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 }