use std::sync::Arc;
use clap::builder::TypedValueParser;
#[derive(Debug, Clone)]
struct Parser<C>(std::marker::PhantomData<C>);
impl<C: ChainSpecParser> TypedValueParser for Parser<C> {
type Value = Arc<C::ChainSpec>;
fn parse_ref(
&self,
_cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
let val =
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
C::parse(val).map_err(|err| {
let arg = arg.map(|a| a.to_string()).unwrap_or_else(|| "...".to_owned());
let possible_values = C::SUPPORTED_CHAINS.join(",");
let msg = format!(
"Invalid value '{val}' for {arg}: {err}.\n [possible values: {possible_values}]"
);
clap::Error::raw(clap::error::ErrorKind::InvalidValue, msg)
})
}
}
pub trait ChainSpecParser: Clone + Send + Sync + 'static {
type ChainSpec: std::fmt::Debug + Send + Sync;
const SUPPORTED_CHAINS: &'static [&'static str];
fn parse(s: &str) -> eyre::Result<Arc<Self::ChainSpec>>;
fn parser() -> impl TypedValueParser<Value = Arc<Self::ChainSpec>> {
Parser(std::marker::PhantomData::<Self>)
}
fn help_message() -> String {
format!("The chain this node is running.\nPossible values are either a built-in chain or the path to a chain specification file.\n\nBuilt-in chains:\n {}", Self::SUPPORTED_CHAINS.join(", "))
}
}