use serde::Serialize;
use std::collections::HashMap;
use std::sync::OnceLock;
#[derive(Debug, Clone, Serialize)]
pub struct ProviderMetadata {
pub name: &'static str,
pub description: &'static str,
pub category: &'static str,
pub parameters: &'static [ProviderParam],
pub example: Option<&'static str>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ProviderParam {
pub name: &'static str,
pub param_type: &'static str,
pub required: bool,
pub description: &'static str,
pub default: Option<&'static str>,
}
pub struct ProviderMetadataRegistry {
providers: HashMap<String, &'static ProviderMetadata>,
}
impl ProviderMetadataRegistry {
pub fn load() -> Self {
let providers = HashMap::new();
Self { providers }
}
pub fn get(&self, name: &str) -> Option<&'static ProviderMetadata> {
self.providers.get(name).copied()
}
pub fn all(&self) -> Vec<&'static ProviderMetadata> {
self.providers.values().copied().collect()
}
pub fn has(&self, name: &str) -> bool {
self.providers.contains_key(name)
}
pub fn register(&mut self, metadata: &'static ProviderMetadata) {
self.providers.insert(metadata.name.to_string(), metadata);
}
}
static PROVIDER_METADATA_REGISTRY: OnceLock<ProviderMetadataRegistry> = OnceLock::new();
pub fn provider_registry() -> &'static ProviderMetadataRegistry {
PROVIDER_METADATA_REGISTRY.get_or_init(ProviderMetadataRegistry::load)
}
#[cfg(test)]
mod tests {
#[shape_macros::shape_provider(category = "Market Data")]
pub fn data_provider() {
}
#[test]
fn test_provider_metadata_generated() {
data_provider();
assert_eq!(PROVIDER_METADATA_DATA.name, "data");
assert_eq!(
PROVIDER_METADATA_DATA.description,
"Test provider for market data"
);
assert_eq!(PROVIDER_METADATA_DATA.category, "Market Data");
assert_eq!(PROVIDER_METADATA_DATA.parameters.len(), 2);
assert_eq!(PROVIDER_METADATA_DATA.parameters[0].name, "symbol");
assert_eq!(PROVIDER_METADATA_DATA.parameters[0].param_type, "String");
assert_eq!(PROVIDER_METADATA_DATA.parameters[0].required, true);
assert_eq!(
PROVIDER_METADATA_DATA.parameters[0].description,
"Stock symbol"
);
assert_eq!(PROVIDER_METADATA_DATA.parameters[1].name, "timeframe");
assert_eq!(PROVIDER_METADATA_DATA.parameters[1].param_type, "String");
assert_eq!(PROVIDER_METADATA_DATA.parameters[1].required, false);
assert_eq!(
PROVIDER_METADATA_DATA.parameters[1].description,
"Time period (optional)"
);
assert_eq!(
PROVIDER_METADATA_DATA.example,
Some(" data('data', {symbol: 'ES', timeframe: '1h'})")
);
}
}