Add branch hints to parser

next
Sayan Nandan 3 years ago
parent 6eaf580ac8
commit 2f7a2d546b

@ -29,6 +29,7 @@ use crate::corestore::memstore::ObjectID;
use crate::kvengine::encoding; use crate::kvengine::encoding;
use crate::protocol::responses; use crate::protocol::responses;
use crate::queryengine::ActionIter; use crate::queryengine::ActionIter;
use crate::util::compiler;
use crate::util::Unwrappable; use crate::util::Unwrappable;
use bytes::Bytes; use bytes::Bytes;
use core::str; use core::str;
@ -41,19 +42,25 @@ const STR: &[u8] = "str".as_bytes();
pub(super) static VALID_CONTAINER_NAME: Lazy<Regex, fn() -> Regex> = pub(super) static VALID_CONTAINER_NAME: Lazy<Regex, fn() -> Regex> =
Lazy::new(|| Regex::new("^[a-zA-Z_$][a-zA-Z_$0-9]*$").unwrap()); Lazy::new(|| Regex::new("^[a-zA-Z_$][a-zA-Z_$0-9]*$").unwrap());
#[cold]
#[inline(never)]
fn cold_err<T>(v: T) -> T {
v
}
pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'static [u8]> { pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'static [u8]> {
let table_name = unsafe { act.next().unsafe_unwrap() }; let table_name = unsafe { act.next().unsafe_unwrap() };
let model_name = unsafe { act.next().unsafe_unwrap() }; let model_name = unsafe { act.next().unsafe_unwrap() };
if !encoding::is_utf8(&table_name) || !encoding::is_utf8(&model_name) { if compiler::unlikely(!encoding::is_utf8(&table_name) || !encoding::is_utf8(&model_name)) {
return Err(responses::groups::ENCODING_ERROR); return Err(responses::groups::ENCODING_ERROR);
} }
let table_name_str = unsafe { str::from_utf8_unchecked(&table_name) }; let table_name_str = unsafe { str::from_utf8_unchecked(&table_name) };
let model_name_str = unsafe { str::from_utf8_unchecked(&model_name) }; let model_name_str = unsafe { str::from_utf8_unchecked(&model_name) };
if !VALID_CONTAINER_NAME.is_match(table_name_str) { if compiler::unlikely(!VALID_CONTAINER_NAME.is_match(table_name_str)) {
return Err(responses::groups::BAD_EXPRESSION); return Err(responses::groups::BAD_EXPRESSION);
} }
let splits: Vec<&str> = model_name_str.split('(').collect(); let splits: Vec<&str> = model_name_str.split('(').collect();
if splits.len() != 2 { if compiler::unlikely(splits.len() != 2) {
return Err(responses::groups::BAD_EXPRESSION); return Err(responses::groups::BAD_EXPRESSION);
} }
let model_name_split = unsafe { splits.get_unchecked(0) }; let model_name_split = unsafe { splits.get_unchecked(0) };
@ -61,7 +68,7 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
// model name has to have at least one char while model args should have // model name has to have at least one char while model args should have
// atleast `)` 1 chars (for example if the model takes no arguments: `smh()`) // atleast `)` 1 chars (for example if the model takes no arguments: `smh()`)
if model_name_split.is_empty() || model_args_split.is_empty() { if compiler::unlikely(model_name_split.is_empty() || model_args_split.is_empty()) {
return Err(responses::groups::BAD_EXPRESSION); return Err(responses::groups::BAD_EXPRESSION);
} }
@ -77,7 +84,7 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
!= b')' != b')'
}; };
if non_bracketed_end { if compiler::unlikely(non_bracketed_end) {
return Err(responses::groups::BAD_EXPRESSION); return Err(responses::groups::BAD_EXPRESSION);
} }
@ -86,21 +93,25 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
.split(',') .split(',')
.map(|v| v.trim()) .map(|v| v.trim())
.collect(); .collect();
if model_args.len() != 2 { if compiler::unlikely(model_args.len() != 2) {
// nope, someone had fun with commas or they added more args // nope, someone had fun with commas or they added more args
// let's check if it was comma fun or if it was arg fun // let's check if it was comma fun or if it was arg fun
let all_nonzero = model_args.into_iter().all(|v| !v.is_empty()); return cold_err({
if all_nonzero { let all_nonzero = model_args.into_iter().all(|v| !v.is_empty());
// arg fun if all_nonzero {
return Err(responses::groups::TOO_MANY_ARGUMENTS); // arg fun
} else { Err(responses::groups::TOO_MANY_ARGUMENTS)
// comma fun } else {
return Err(responses::groups::BAD_EXPRESSION); // comma fun
} Err(responses::groups::BAD_EXPRESSION)
}
});
} }
let key_ty = unsafe { model_args.get_unchecked(0) }; let key_ty = unsafe { model_args.get_unchecked(0) };
let val_ty = unsafe { model_args.get_unchecked(1) }; let val_ty = unsafe { model_args.get_unchecked(1) };
if !VALID_CONTAINER_NAME.is_match(key_ty) || !VALID_CONTAINER_NAME.is_match(val_ty) { if compiler::unlikely(
!VALID_CONTAINER_NAME.is_match(key_ty) || !VALID_CONTAINER_NAME.is_match(val_ty),
) {
return Err(responses::groups::BAD_EXPRESSION); return Err(responses::groups::BAD_EXPRESSION);
} }
let key_ty = key_ty.as_bytes(); let key_ty = key_ty.as_bytes();
@ -113,11 +124,11 @@ pub(super) fn parse_table_args(mut act: ActionIter) -> Result<(ObjectID, u8), &'
_ => return Err(responses::groups::UNKNOWN_DATA_TYPE), _ => return Err(responses::groups::UNKNOWN_DATA_TYPE),
}; };
if table_name_str.len() > 64 { if compiler::unlikely(table_name_str.len() > 64) {
return Err(responses::groups::CONTAINER_NAME_TOO_LONG); Err(responses::groups::CONTAINER_NAME_TOO_LONG)
} else {
Ok((unsafe { ObjectID::from_slice(table_name_str) }, model_code))
} }
Ok((unsafe { ObjectID::from_slice(table_name_str) }, model_code))
} }
pub type EntityGroup<'a> = (Option<&'a [u8]>, Option<&'a [u8]>); pub type EntityGroup<'a> = (Option<&'a [u8]>, Option<&'a [u8]>);
@ -128,7 +139,7 @@ pub(super) fn get_query_entity<'a>(input: &'a Bytes) -> Result<EntityGroup<'a>,
if y.len() == 1 { if y.len() == 1 {
// just tbl // just tbl
let tblret = y.get_unchecked(0); let tblret = y.get_unchecked(0);
if tblret.len() > 64 || tblret.is_empty() { if compiler::unlikely(tblret.len() > 64 || tblret.is_empty()) {
Err(responses::groups::BAD_CONTAINER_NAME) Err(responses::groups::BAD_CONTAINER_NAME)
} else { } else {
Ok((None, Some(tblret))) Ok((None, Some(tblret)))
@ -137,16 +148,16 @@ pub(super) fn get_query_entity<'a>(input: &'a Bytes) -> Result<EntityGroup<'a>,
// tbl + ns // tbl + ns
let ksret = y.get_unchecked(0); let ksret = y.get_unchecked(0);
let tblret = y.get_unchecked(1); let tblret = y.get_unchecked(1);
if ksret.len() > 64 || tblret.len() > 64 { if compiler::unlikely(ksret.len() > 64 || tblret.len() > 64) {
Err(responses::groups::BAD_CONTAINER_NAME) Err(responses::groups::BAD_CONTAINER_NAME)
} else if tblret.is_empty() || ksret.is_empty() { } else if compiler::unlikely(tblret.is_empty() || ksret.is_empty()) {
Err(responses::groups::BAD_EXPRESSION) Err(responses::groups::BAD_EXPRESSION)
} else { } else {
Ok((Some(ksret), Some(tblret))) Ok((Some(ksret), Some(tblret)))
} }
} else { } else {
// something wrong // something wrong
Err(responses::groups::BAD_EXPRESSION) cold_err(Err(responses::groups::BAD_EXPRESSION))
} }
} }
} }

Loading…
Cancel
Save