#![cfg(feature = "ext-bazaar")]
#![cfg_attr(docsrs, doc(cfg(feature = "ext-bazaar")))]
use compact_str::CompactString;
use serde_json::Value;
use super::{AdvertiseContext, Extension};
use crate::wire::ExtensionEntry;
#[derive(Debug, Clone, Default)]
pub struct BazaarExtension {
pub catalog: Option<CompactString>,
pub categories: Vec<CompactString>,
pub registered: bool,
}
impl BazaarExtension {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_catalog(mut self, catalog: impl Into<CompactString>) -> Self {
self.catalog = Some(catalog.into());
self
}
#[must_use]
pub fn with_category(mut self, category: impl Into<CompactString>) -> Self {
self.categories.push(category.into());
self
}
#[must_use]
pub const fn registered(mut self) -> Self {
self.registered = true;
self
}
}
impl Extension for BazaarExtension {
fn id(&self) -> &'static str {
"bazaar"
}
fn advertise(&self, _ctx: &AdvertiseContext<'_>) -> Option<ExtensionEntry> {
let mut info = serde_json::Map::new();
if let Some(catalog) = &self.catalog {
let _ = info.insert("catalog".to_owned(), Value::String(catalog.to_string()));
}
if !self.categories.is_empty() {
let cats: Vec<Value> = self
.categories
.iter()
.map(|c| Value::String(c.to_string()))
.collect();
let _ = info.insert("categories".to_owned(), Value::Array(cats));
}
let _ = info.insert("registered".to_owned(), Value::Bool(self.registered));
Some(ExtensionEntry::info(Value::Object(info)))
}
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn advertise_includes_catalog_and_categories() {
let ext = BazaarExtension::new()
.with_catalog("https://example.com/catalog")
.with_category("data")
.with_category("api")
.registered();
let ctx = AdvertiseContext { requirement: None };
let entry = ext.advertise(&ctx).unwrap();
let info = entry.as_info().unwrap();
assert_eq!(info["catalog"], "https://example.com/catalog");
assert_eq!(info["registered"], true);
assert_eq!(info["categories"], json!(["data", "api"]));
}
#[test]
fn advertise_minimal_emits_registered_flag() {
let ext = BazaarExtension::new();
let ctx = AdvertiseContext { requirement: None };
let entry = ext.advertise(&ctx).unwrap();
let info = entry.as_info().unwrap();
assert_eq!(info["registered"], false);
assert!(info.get("catalog").is_none());
}
}