use super::{ProviderInfo, ProviderUrl, ProviderWithPreflight};
use crate::Result;
#[doc(hidden)]
pub struct ProviderRegistration {
pub info: ProviderInfo,
pub schemes: &'static [&'static str],
pub factory: fn(&ProviderUrl) -> Result<ProviderWithPreflight>,
}
#[doc(hidden)]
#[linkme::distributed_slice]
pub static PROVIDER_REGISTRY: [ProviderRegistration];
#[doc(hidden)]
#[macro_export]
macro_rules! register_provider {
(
struct: $struct_name:ident,
config: $config_type:ty,
name: $name:expr,
description: $description:expr,
schemes: [$($scheme:expr),* $(,)?],
examples: [$($example:expr),* $(,)?] $(,)?
) => {
$crate::register_provider!(@register
$struct_name, $config_type, $name, $description,
[$($scheme,)*], [$($example,)*],
|provider| {
Ok($crate::provider::ProviderWithPreflight {
provider: Box::new(provider),
preflight: None,
})
}
);
};
(
struct: $struct_name:ident,
config: $config_type:ty,
name: $name:expr,
description: $description:expr,
schemes: [$($scheme:expr),* $(,)?],
examples: [$($example:expr),* $(,)?],
preflight: $preflight:ident $(,)?
) => {
$crate::register_provider!(@register
$struct_name, $config_type, $name, $description,
[$($scheme,)*], [$($example,)*],
|provider| {
let provider = std::sync::Arc::new(provider);
let preflight_provider = std::sync::Arc::clone(&provider);
Ok($crate::provider::ProviderWithPreflight {
provider: Box::new(provider),
preflight: Some(Box::new(move || preflight_provider.$preflight())),
})
}
);
};
(@register
$struct_name:ident, $config_type:ty, $name:expr, $description:expr,
[$($scheme:expr,)*], [$($example:expr,)*],
$wrap:expr
) => {
impl $struct_name {
const PROVIDER_NAME: &'static str = $name;
}
const _: () = {
#[linkme::distributed_slice($crate::provider::PROVIDER_REGISTRY)]
#[doc(hidden)]
static PROVIDER_REGISTRATION: $crate::provider::ProviderRegistration = $crate::provider::ProviderRegistration {
info: $crate::provider::ProviderInfo {
name: $name,
description: $description,
examples: &[$($example,)*],
},
schemes: &[$($scheme,)*],
factory: |url| {
let config = <$config_type>::try_from(url)?;
let provider = <$struct_name>::new(config);
let wrap: fn($struct_name) -> $crate::Result<$crate::provider::ProviderWithPreflight> = $wrap;
wrap(provider)
},
};
};
};
}