use super::{
resp_command_key_specification::{
BeginSearchMethod, FindKeysMethod, KeySpecificationFlags, RespCommandKeySpecification,
},
resp_commands_info::{RespCommandFlags, RespCommandsInfo, StoreType},
};
#[derive(Debug, Clone)]
pub struct SimpleRespCommandInfo {
pub arity: i8,
pub allowed_in_txn: bool,
pub is_parent: bool,
pub is_sub_command: bool,
pub key_specs: Vec<SimpleRespKeySpec>,
pub store_type: StoreType,
}
impl Default for SimpleRespCommandInfo {
fn default() -> Self {
Self {
arity: 0,
allowed_in_txn: false,
is_parent: false,
is_sub_command: false,
key_specs: Vec::new(),
store_type: StoreType::None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct SimpleRespKeySpecBeginSearch {
pub keyword: Vec<u8>,
pub index: i32,
pub is_index_type: bool,
}
#[derive(Debug, Clone, Default)]
pub struct SimpleRespKeySpecFindKeys {
pub key_num_index: i32,
pub first_key: i32,
pub last_key_or_limit: i32,
pub key_step: i32,
pub is_range_type: bool,
pub is_range_limit_type: bool,
}
#[derive(Debug, Clone, Default)]
pub struct SimpleRespKeySpec {
pub begin_search: SimpleRespKeySpecBeginSearch,
pub find_keys: SimpleRespKeySpecFindKeys,
pub flags: KeySpecificationFlags,
}
pub fn populate_simple_command_info(
cmd_info: &RespCommandsInfo,
simple_cmd_info: &mut SimpleRespCommandInfo,
) {
simple_cmd_info.arity = cmd_info.arity as i8;
simple_cmd_info.allowed_in_txn = !cmd_info.flags.intersects(RespCommandFlags::NO_MULTI);
simple_cmd_info.is_parent = !cmd_info.sub_commands.is_empty();
simple_cmd_info.is_sub_command = cmd_info.is_sub_command;
simple_cmd_info.store_type = cmd_info.store_type;
let mut tmp_simple_key_specs = Vec::new();
for key_spec in &cmd_info.key_specifications {
if let Some(simple_key_spec) = try_get_simple_key_spec(key_spec) {
tmp_simple_key_specs.push(simple_key_spec);
}
}
simple_cmd_info.key_specs = tmp_simple_key_specs;
}
pub fn try_get_simple_key_spec(
key_spec: &RespCommandKeySpecification,
) -> Option<SimpleRespKeySpec> {
if matches!(key_spec.begin_search, Some(BeginSearchMethod::Unknown))
|| matches!(key_spec.find_keys, Some(FindKeysMethod::Unknown))
{
return None;
}
let begin_search = match key_spec.begin_search.as_ref()? {
BeginSearchMethod::Index(index) => SimpleRespKeySpecBeginSearch {
keyword: Vec::new(),
index: *index,
is_index_type: true,
},
BeginSearchMethod::Keyword {
keyword,
start_from,
} => SimpleRespKeySpecBeginSearch {
keyword: keyword.as_bytes().to_vec(),
index: *start_from,
is_index_type: false,
},
BeginSearchMethod::Unknown => return None,
};
let find_keys = match key_spec.find_keys.as_ref()? {
FindKeysMethod::Range {
last_key,
key_step,
limit,
} => {
if *last_key == -1 {
SimpleRespKeySpecFindKeys {
key_num_index: 0,
first_key: 0,
last_key_or_limit: *limit,
key_step: *key_step,
is_range_type: true,
is_range_limit_type: true,
}
} else {
SimpleRespKeySpecFindKeys {
key_num_index: 0,
first_key: 0,
last_key_or_limit: *last_key,
key_step: *key_step,
is_range_type: true,
is_range_limit_type: false,
}
}
}
FindKeysMethod::KeyNum {
key_num_idx,
first_key,
key_step,
} => SimpleRespKeySpecFindKeys {
key_num_index: *key_num_idx,
first_key: *first_key,
last_key_or_limit: 0,
key_step: *key_step,
is_range_type: false,
is_range_limit_type: false,
},
FindKeysMethod::Unknown => return None,
};
Some(SimpleRespKeySpec {
begin_search,
find_keys,
flags: key_spec.flags,
})
}