use super::command_catalog_data::CMD_ENTRIES;
pub(crate) use super::command_catalog_data::CmdEntry;
use crate::types::RespCommand;
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RespAclCategories: u32 {
const ADMIN = 1;
const BITMAP = 1 << 1;
const BLOCKING = 1 << 2;
const CONNECTION = 1 << 3;
const DANGEROUS = 1 << 4;
const GEO = 1 << 5;
const HASH = 1 << 6;
const HYPERLOGLOG = 1 << 7;
const FAST = 1 << 8;
const KEYSPACE = 1 << 9;
const LIST = 1 << 10;
const PUBSUB = 1 << 11;
const READ = 1 << 12;
const SCRIPTING = 1 << 13;
const SET = 1 << 14;
const SORTEDSET = 1 << 15;
const SLOW = 1 << 16;
const STREAM = 1 << 17;
const STRING = 1 << 18;
const TRANSACTION = 1 << 19;
const WRITE = 1 << 20;
const GARNET = 1 << 21;
const CUSTOM = 1 << 22;
const VECTOR = 1 << 23;
const ALL = (1 << 24) - 1;
}
}
const EXPANDED_SET: [RespCommand; 4] = [
RespCommand::Setexnx,
RespCommand::Setexxx,
RespCommand::Setkeepttl,
RespCommand::Setkeepttlxx,
];
const EXPANDED_BITOP: [RespCommand; 5] = [
RespCommand::BitopAnd,
RespCommand::BitopNot,
RespCommand::BitopOr,
RespCommand::BitopXor,
RespCommand::BitopDiff,
];
#[inline]
pub const fn normalize_for_acls(cmd: RespCommand) -> RespCommand {
match cmd {
RespCommand::Setexnx
| RespCommand::Setexxx
| RespCommand::Setkeepttl
| RespCommand::Setkeepttlxx => RespCommand::Set,
RespCommand::BitopAnd
| RespCommand::BitopNot
| RespCommand::BitopOr
| RespCommand::BitopXor
| RespCommand::BitopDiff => RespCommand::Bitop,
_ => cmd,
}
}
#[inline]
pub fn expand_for_acls(cmd: RespCommand) -> &'static [RespCommand] {
match cmd {
RespCommand::Set => &EXPANDED_SET,
RespCommand::Bitop => &EXPANDED_BITOP,
_ => &[],
}
}
#[inline]
pub const fn is_no_auth(cmd: RespCommand) -> bool {
let v = (cmd as u16).wrapping_sub(RespCommand::Auth as u16);
v <= (RespCommand::Quit as u16).wrapping_sub(RespCommand::Auth as u16)
}
pub const LAST_VALID_COMMAND: RespCommand = RespCommand::Quit;
#[inline]
pub(crate) fn try_get_resp_command_info(cmd: RespCommand) -> Option<&'static CmdEntry> {
CMD_ENTRIES.iter().find(|e| e.cmd == cmd)
}
#[inline]
pub(crate) fn try_get_by_cs_name(name: &str) -> Option<&'static CmdEntry> {
CMD_ENTRIES.iter().find(|e| e.cs.eq_ignore_ascii_case(name))
}
#[inline]
pub(crate) fn children_of(cmd: RespCommand) -> impl Iterator<Item = &'static CmdEntry> {
CMD_ENTRIES.iter().filter(move |e| e.parent == Some(cmd))
}
pub(crate) fn try_get_commands_for_acl_category(
acl: RespAclCategories,
) -> Option<Vec<&'static CmdEntry>> {
if acl.is_empty() {
return None;
}
let members: Vec<_> = CMD_ENTRIES
.iter()
.filter(|e| e.cats.intersects(acl))
.collect();
Some(members)
}