use std::{collections::HashMap, error::Error, str::FromStr};
use crate::Result;
use clap::Subcommand;
use tansu_sans_io::ErrorCode;
use tansu_topic::Topic;
use url::Url;
use super::DEFAULT_BROKER;
#[derive(Clone, Debug, Subcommand)]
pub(super) enum Command {
Create {
#[arg(long, default_value = DEFAULT_BROKER)]
broker: Url,
#[clap(value_parser)]
name: String,
#[arg(long, default_value = "3")]
partitions: i32,
#[arg(long, value_parser = parse_key_val::<String, String>)]
config: Vec<(String, String)>,
},
Delete {
#[arg(long, default_value = DEFAULT_BROKER)]
broker: Url,
#[clap(value_parser)]
name: String,
},
List {
#[arg(long, default_value = DEFAULT_BROKER)]
broker: Url,
},
}
impl From<Command> for Topic {
fn from(value: Command) -> Self {
match value {
Command::Create {
broker,
name,
partitions,
config,
} => Topic::create()
.broker(broker)
.name(name)
.partitions(partitions)
.config(HashMap::from_iter(config))
.build(),
Command::Delete { broker, name } => Topic::delete().broker(broker).name(name).build(),
Command::List { broker } => Topic::list().broker(broker).build(),
}
}
}
impl Command {
pub(super) async fn main(self) -> Result<ErrorCode> {
Topic::from(self).main().await.map_err(Into::into)
}
}
fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
where
T: FromStr,
T::Err: Error + Send + Sync + 'static,
U: FromStr,
U::Err: Error + Send + Sync + 'static,
{
let pos = s
.find('=')
.ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
Ok((s[..pos].parse()?, s[pos + 1..].parse()?))
}