mod macros;
mod parse;
mod reporting;
mod schema;
use crate::parse::CliArgs;
use crate::schema::{IntoSchema, Schema, SchemaKind};
use std::any::Any;
pub use error::SchemaError;
pub use macros::*;
pub type Result<T> = std::result::Result<T, SchemaError>;
pub fn badargs<S>() -> BadArgs
where
S: IntoSchema,
{
let arg_schema = Schema::create::<S>().expect("Invalid schema");
let args = CliArgs::from_args(&arg_schema, std::env::args_os());
match args {
Ok(args) => BadArgs { args },
Err(err) => reporting::report(err, &arg_schema),
}
}
pub trait CliArg: Any {
type Content: CliReturnValue;
fn long() -> &'static str;
fn short() -> Option<char>;
}
#[derive(Debug, Default)]
pub struct BadArgs {
args: CliArgs,
}
impl BadArgs {
pub fn get<T>(&self) -> Option<&T::Content>
where
T: CliArg,
{
let long_name = T::long();
self.args.get::<T::Content>(long_name)
}
pub fn unnamed(&self) -> &[String] {
self.args.unnamed()
}
}
pub trait CliReturnValue: sealed::SealedCliReturnValue {
fn kind() -> schema::SchemaKind;
}
macro_rules! impl_cli_return {
($(for $ty:ty => $type:ident);+;) => {$(
impl CliReturnValue for $ty {
fn kind() -> SchemaKind {
SchemaKind::$type
}
}
)+};
}
impl_cli_return!(
for String => String;
for bool => Bool;
for isize => IInt;
for usize => UInt;
for f64 => Num;
);
mod sealed {
pub trait SealedCliReturnValue {}
macro_rules! impl_ {
($($name:ty),+) => {$(impl SealedCliReturnValue for $name{})+};
}
impl_!(String, bool, usize, isize, f64);
}
mod error {
use crate::schema::SchemaKind;
use std::ffi::OsString;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum SchemaError {
NameAlreadyExists(String),
InvalidSchema(String),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum CallError {
ShortFlagNotFound(char),
LongFlagNotFound(String),
ExpectedValue(String, SchemaKind),
INan(String),
UNan(String),
NNan(String),
CombinedShortWithValue(String),
InvalidUtf8(OsString),
HelpPage,
}
}