use super::{Anyhow, ArgumentName, CommandParseError, IdParseError};
#[derive(Debug)]
pub enum Downcast {
CommandParse(CommandParseError),
IdParse(IdParseError),
Other(Anyhow),
}
impl From<Anyhow> for Downcast {
fn from(anyhow: Anyhow) -> Self {
anyhow.downcast().map_or_else(
|e| e.downcast().map_or_else(Self::Other, Self::IdParse),
Self::CommandParse,
)
}
}
pub trait FoldError {
type Output;
fn fold_anyhow(&self, err: Anyhow) -> Self::Output {
match err.into() {
Downcast::CommandParse(c) => self.fold_command_parse(c),
Downcast::IdParse(i) => self.fold_id_parse(i),
Downcast::Other(o) => self.other(o),
}
}
fn fold_id_parse(&self, err: IdParseError) -> Self::Output {
match err {
IdParseError::NoMatch(given, available) => self.no_id_match(given, available),
IdParseError::Ambiguous(possible, given) => self.ambiguous_id(possible, given),
}
}
fn fold_command_parse(&self, err: CommandParseError) -> Self::Output {
match err {
CommandParseError::NoInput => self.no_input(),
CommandParseError::BadId(i) => self.bad_id(i),
CommandParseError::MissingRequired(ArgumentName { cmd, arg }) => {
self.missing_required(cmd, arg)
},
CommandParseError::BadConvert(ArgumentName { cmd, arg }, e) => {
self.bad_convert(cmd, arg, self.fold_anyhow(e))
},
CommandParseError::Trailing(c, t) => self.trailing(c, t),
CommandParseError::Subcommand(s, e) => {
self.subcommand(s, self.fold_command_parse(Box::into_inner(e)))
},
}
}
fn no_id_match(&self, given: String, available: &'static [&'static str]) -> Self::Output;
fn ambiguous_id(&self, possible: &'static [&'static str], given: String) -> Self::Output;
fn no_input(&self) -> Self::Output;
fn bad_id(&self, err: IdParseError) -> Self::Output { self.fold_id_parse(err) }
fn missing_required(&self, cmd: &'static str, arg: &'static str) -> Self::Output;
fn bad_convert(
&self,
cmd: &'static str,
arg: &'static str,
inner: Self::Output,
) -> Self::Output;
fn trailing(&self, cmd: &'static str, extra: String) -> Self::Output;
fn subcommand(&self, subcmd: &'static str, inner: Self::Output) -> Self::Output;
fn other(&self, error: Anyhow) -> Self::Output;
}