use yo_common::Result;
use yo_search::Registry;
use yo_search::config::{Config, EXCESS, Kind, TABLE, UNKNOWN};
use super::Args;
use crate::dispatch::args;
use crate::reply::Out;
const NAME: &str = "FT.CONFIG";
pub(super) fn run(reg: &mut Registry, args: Args<'_>, out: &mut Out) -> Result<()> {
let sub = args.get(1);
let wanted = |what: &str| args::wrong_arity_sub(NAME, what);
match sub {
_ if args::is(sub, b"GET") => {
if args.len() < 3 {
return Err(wanted("GET"));
}
dump(®.config, args.get(2), out, false);
}
_ if args::is(sub, b"HELP") => {
if args.len() < 3 {
return Err(wanted("HELP"));
}
dump(®.config, args.get(2), out, true);
}
_ if args::is(sub, b"SET") => {
if args.len() < 3 {
return Err(wanted("SET"));
}
set(&mut reg.config, args, out);
}
_ => return Err(args::unknown_subcommand(sub, NAME)),
}
Ok(())
}
fn dump(config: &Config, name: &[u8], out: &mut Out, helping: bool) {
let rows: Vec<usize> = if name == b"*" {
(0..TABLE.len()).collect()
} else {
Config::find(name).into_iter().collect()
};
let three = out.proto().is_resp3();
if three {
out.map(rows.len());
} else {
out.array(rows.len());
}
for at in rows {
if !three {
out.array(if helping { 5 } else { 2 });
}
out.simple(TABLE[at].name.as_bytes());
if helping {
if three {
out.map(2);
}
out.simple(b"Description");
out.simple(TABLE[at].help.as_bytes());
out.simple(b"Value");
}
match config.value(at) {
Some(value) => out.bulk(&value),
None => out.nil(),
}
}
}
fn set(config: &mut Config, args: Args<'_>, out: &mut Out) {
let Some(at) = Config::find(args.get(2)) else {
out.error(UNKNOWN.as_bytes());
return;
};
let takes = if matches!(TABLE[at].kind, Kind::Bare) {
3
} else {
4
};
let value = (args.len() > 3).then(|| args.get(3));
if let Err(why) = config.set(at, value) {
out.error(&why);
return;
}
if args.len() > takes {
out.simple(EXCESS);
return;
}
out.ok();
}