use std::marker::PhantomData;
pub use clap;
use schemars::JsonSchema;
use crate::{
CliContract, CliSchema, ContractBuilder, Result, contract::RegistrationState,
schema::extended_schema_factory,
};
#[doc(hidden)]
pub trait HandlerContract: 'static {
type Output: JsonSchema + 'static;
}
pub trait HandlerResult {
type Output: JsonSchema + 'static;
}
impl<T, E> HandlerResult for std::result::Result<T, E>
where
T: JsonSchema + 'static,
{
type Output = T;
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct PayloadRegistration<T>(PhantomData<fn() -> T>);
impl<T> PayloadRegistration<T> {
#[must_use]
pub const fn new() -> Self {
Self(PhantomData)
}
}
impl<T> Default for PayloadRegistration<T> {
fn default() -> Self {
Self::new()
}
}
#[doc(hidden)]
pub trait RegisterPayload {
fn register(self, prefix: &mut Vec<String>, registry: &mut Registry) -> Result<bool>;
}
impl<T> RegisterPayload for PayloadRegistration<T>
where
T: crate::CommandSchema,
{
fn register(self, prefix: &mut Vec<String>, registry: &mut Registry) -> Result<bool> {
T::__clap_schema_register(prefix, registry)?;
Ok(true)
}
}
impl<T> RegisterPayload for &PayloadRegistration<T>
where
T: HandlerContract,
{
fn register(self, prefix: &mut Vec<String>, registry: &mut Registry) -> Result<bool> {
registry.command::<T>(prefix);
Ok(false)
}
}
#[doc(hidden)]
pub trait RegisterPayloadExtended {
fn register_extended<E>(
self,
prefix: &mut Vec<String>,
registry: &mut Registry,
) -> Result<bool>
where
E: JsonSchema;
}
impl<T> RegisterPayloadExtended for PayloadRegistration<T>
where
T: crate::CommandSchema + 'static,
{
fn register_extended<E>(self, prefix: &mut Vec<String>, registry: &mut Registry) -> Result<bool>
where
E: JsonSchema,
{
T::__clap_schema_register(prefix, registry)?;
registry.command_extension::<T, E>(prefix)?;
Ok(true)
}
}
impl<T> RegisterPayloadExtended for &PayloadRegistration<T>
where
T: HandlerContract,
{
fn register_extended<E>(self, prefix: &mut Vec<String>, registry: &mut Registry) -> Result<bool>
where
E: JsonSchema,
{
registry.command_extended::<T, E>(prefix);
Ok(false)
}
}
#[derive(Debug, Default)]
pub struct Registry {
registration: RegistrationState,
}
impl Registry {
pub fn command<T>(&mut self, path: &[String])
where
T: HandlerContract,
{
self.registration.command::<T>(path.to_vec(), None);
}
pub fn command_extended<T, E>(&mut self, path: &[String])
where
T: HandlerContract,
E: JsonSchema,
{
self.registration.command::<T>(path.to_vec(), Some(extended_schema_factory::<E>()));
}
pub fn command_extension<T, E>(&mut self, path: &[String]) -> Result<()>
where
T: 'static,
E: JsonSchema,
{
self.registration.command_extension::<T>(path, extended_schema_factory::<E>())
}
pub fn extend<T>(&mut self)
where
T: JsonSchema,
{
self.registration.extend(extended_schema_factory::<T>());
}
}
pub fn build_derived<T>() -> Result<CliContract>
where
T: CliSchema,
{
let mut registry = Registry::default();
T::__clap_schema_register(&mut registry)?;
ContractBuilder::with_registration(T::command(), registry.registration).build()
}