Use proc macro for correct compile-time response generation

next
Sayan Nandan 3 years ago
parent 2c6768dc12
commit 72304195d1
No known key found for this signature in database
GPG Key ID: 8BC07A0A4D41DD52

@ -8,6 +8,7 @@ version = "0.7.5"
[dependencies]
# internal deps
libsky = { path = "../libsky" }
sky_macros = { path = "../sky-macros" }
# external deps
ahash = "0.7.6"
bytes = "1.1.0"
@ -40,7 +41,6 @@ cc = "1.0.73"
[dev-dependencies]
# internal deps
sky_macros = { path = "../sky-macros" }
libstress = { path = "../libstress" }
skytable = { git = "https://github.com/skytable/client-rust", features = [
"aio",

@ -31,81 +31,83 @@ pub mod groups {
//! # Pre-compiled response **elements**
//! These are pre-compiled response groups and **not** complete responses. If complete
//! responses are required, user protocol::responses::fresp
use ::sky_macros::compiled_eresp_bytes as eresp;
/// Response code 0 as a array element
pub const OKAY: &[u8] = "!1\n0\n".as_bytes();
pub const OKAY: &[u8] = eresp!("0");
/// Response code 1 as a array element
pub const NIL: &[u8] = "!1\n1\n".as_bytes();
pub const NIL: &[u8] = eresp!("1");
/// Response code 2 as a array element
pub const OVERWRITE_ERR: &[u8] = "!1\n2\n".as_bytes();
pub const OVERWRITE_ERR: &[u8] = eresp!("2");
/// Response code 3 as a array element
pub const ACTION_ERR: &[u8] = "!1\n3\n".as_bytes();
pub const ACTION_ERR: &[u8] = eresp!("3");
/// Response code 4 as a array element
pub const PACKET_ERR: &[u8] = "!1\n4\n".as_bytes();
pub const PACKET_ERR: &[u8] = eresp!("4");
/// Response code 5 as a array element
pub const SERVER_ERR: &[u8] = "!1\n5\n".as_bytes();
pub const SERVER_ERR: &[u8] = eresp!("5");
/// Response code 6 as a array element
pub const OTHER_ERR_EMPTY: &[u8] = "!1\n6\n".as_bytes();
pub const OTHER_ERR_EMPTY: &[u8] = eresp!("6");
/// Response group element with string "HEYA"
pub const HEYA: &[u8] = "+4\nHEY!\n".as_bytes();
/// "Unknown action" error response
pub const UNKNOWN_ACTION: &[u8] = "!14\nUnknown action\n".as_bytes();
pub const UNKNOWN_ACTION: &[u8] = eresp!("Unknown action");
/// Response code 7
pub const WRONGTYPE_ERR: &[u8] = "!1\n7\n".as_bytes();
pub const WRONGTYPE_ERR: &[u8] = eresp!("7");
/// Response code 8
pub const UNKNOWN_DATA_TYPE: &[u8] = "!1\n8\n".as_bytes();
pub const UNKNOWN_DATA_TYPE: &[u8] = eresp!("8");
/// Response code 9 as an array element
pub const ENCODING_ERROR: &[u8] = "!1\n9\n".as_bytes();
pub const ENCODING_ERROR: &[u8] = eresp!("9");
/// Snapshot busy error
pub const SNAPSHOT_BUSY: &[u8] = "!17\nerr-snapshot-busy\n".as_bytes();
pub const SNAPSHOT_BUSY: &[u8] = eresp!("err-snapshot-busy");
/// Snapshot disabled (other error)
pub const SNAPSHOT_DISABLED: &[u8] = "!21\nerr-snapshot-disabled\n".as_bytes();
pub const SNAPSHOT_DISABLED: &[u8] = eresp!("err-snapshot-disabled");
/// Duplicate snapshot
pub const SNAPSHOT_DUPLICATE: &[u8] = "!18\nduplicate-snapshot\n".as_bytes();
pub const SNAPSHOT_DUPLICATE: &[u8] = eresp!("duplicate-snapshot");
/// Snapshot has illegal name (other error)
pub const SNAPSHOT_ILLEGAL_NAME: &[u8] = "!25\nerr-invalid-snapshot-name\n".as_bytes();
pub const SNAPSHOT_ILLEGAL_NAME: &[u8] = eresp!("err-invalid-snapshot-name");
/// Access after termination signal (other error)
pub const ERR_ACCESS_AFTER_TERMSIG: &[u8] = "!24\nerr-access-after-termsig\n".as_bytes();
pub const ERR_ACCESS_AFTER_TERMSIG: &[u8] = eresp!("err-access-after-termsig");
// keyspace related resps
/// The default container was not set
pub const DEFAULT_UNSET: &[u8] = "!23\ndefault-container-unset\n".as_bytes();
pub const DEFAULT_UNSET: &[u8] = eresp!("default-container-unset");
/// The container was not found
pub const CONTAINER_NOT_FOUND: &[u8] = "!19\ncontainer-not-found\n".as_bytes();
pub const CONTAINER_NOT_FOUND: &[u8] = eresp!("container-not-found");
/// The container is still in use and so cannot be removed
pub const STILL_IN_USE: &[u8] = "!12\nstill-in-use\n".as_bytes();
pub const STILL_IN_USE: &[u8] = eresp!("still-in-use");
/// This is a protected object and hence cannot be accessed
pub const PROTECTED_OBJECT: &[u8] = "!20\nerr-protected-object\n".as_bytes();
pub const PROTECTED_OBJECT: &[u8] = eresp!("err-protected-object");
/// The action was applied against the wrong model
pub const WRONG_MODEL: &[u8] = "!11\nwrong-model\n".as_bytes();
pub const WRONG_MODEL: &[u8] = eresp!("wrong-model");
/// The container already exists
pub const ALREADY_EXISTS: &[u8] = "!18\nerr-already-exists\n".as_bytes();
pub const ALREADY_EXISTS: &[u8] = eresp!("err-already-exists");
/// The container is not ready
pub const NOT_READY: &[u8] = "!9\nnot-ready\n".as_bytes();
pub const NOT_READY: &[u8] = eresp!("not-ready");
/// A transactional failure occurred
pub const DDL_TRANSACTIONAL_FAILURE: &[u8] = "!21\ntransactional-failure\n".as_bytes();
pub const DDL_TRANSACTIONAL_FAILURE: &[u8] = eresp!("transactional-failure");
/// An unknown DDL query was run
pub const UNKNOWN_DDL_QUERY: &[u8] = "!17\nunknown-ddl-query\n".as_bytes();
pub const UNKNOWN_DDL_QUERY: &[u8] = eresp!("unknown-ddl-query");
/// The expression for a DDL query was malformed
pub const BAD_EXPRESSION: &[u8] = "!20\nmalformed-expression\n".as_bytes();
pub const BAD_EXPRESSION: &[u8] = eresp!("malformed-expression");
/// An unknown model was passed in a DDL query
pub const UNKNOWN_MODEL: &[u8] = "!13\nunknown-model\n".as_bytes();
pub const UNKNOWN_MODEL: &[u8] = eresp!("unknown-model");
/// Too many arguments were passed to model constructor
pub const TOO_MANY_ARGUMENTS: &[u8] = "!13\ntoo-many-args\n".as_bytes();
pub const TOO_MANY_ARGUMENTS: &[u8] = eresp!("too-many-args");
/// The container name is too long
pub const CONTAINER_NAME_TOO_LONG: &[u8] = "!23\ncontainer-name-too-long\n".as_bytes();
pub const CONTAINER_NAME_TOO_LONG: &[u8] = eresp!("container-name-too-long");
/// The container name contains invalid characters
pub const BAD_CONTAINER_NAME: &[u8] = "!18\nbad-container-name\n".as_bytes();
pub const BAD_CONTAINER_NAME: &[u8] = eresp!("bad-container-name");
/// An unknown inspect query
pub const UNKNOWN_INSPECT_QUERY: &[u8] = "!21\nunknown-inspect-query\n".as_bytes();
pub const UNKNOWN_INSPECT_QUERY: &[u8] = eresp!("unknown-inspect-query");
/// An unknown table property was passed
pub const UNKNOWN_PROPERTY: &[u8] = "!16\nunknown-property\n".as_bytes();
pub const UNKNOWN_PROPERTY: &[u8] = eresp!("unknown-property");
/// The keyspace is not empty and hence cannot be removed
pub const KEYSPACE_NOT_EMPTY: &[u8] = "!18\nkeyspace-not-empty\n".as_bytes();
pub const KEYSPACE_NOT_EMPTY: &[u8] = eresp!("keyspace-not-empty");
/// Bad type supplied in a DDL query for the key
pub const BAD_TYPE_FOR_KEY: &[u8] = "!16\nbad-type-for-key\n".as_bytes();
pub const BAD_TYPE_FOR_KEY: &[u8] = eresp!("bad-type-for-key");
/// The index for the provided list was non-existent
pub const LISTMAP_BAD_INDEX: &[u8] = "!14\nbad-list-index\n".as_bytes();
pub const LISTMAP_LIST_IS_EMPTY: &[u8] = "!13\nlist-is-empty\n".as_bytes();
pub const LISTMAP_BAD_INDEX: &[u8] = eresp!("bad-list-index");
/// The list is empty
pub const LISTMAP_LIST_IS_EMPTY: &[u8] = eresp!("list-is-empty");
}
pub mod full_responses {

@ -44,6 +44,8 @@
//!
use proc_macro::TokenStream;
use quote::quote;
use syn::Lit;
mod dbtest_fn;
mod dbtest_mod;
@ -99,3 +101,57 @@ pub fn dbtest_module(args: TokenStream, item: TokenStream) -> TokenStream {
pub fn dbtest_func(args: TokenStream, item: TokenStream) -> TokenStream {
dbtest_fn::dbtest_func(args, item)
}
#[proc_macro]
/// Get a compile time respcode/respstring array. For example, if you pass: "Unknown action",
/// it will return: `!14\nUnknown Action\n`
pub fn compiled_eresp_array(tokens: TokenStream) -> TokenStream {
_get_eresp_array(tokens)
}
fn _get_eresp_array(tokens: TokenStream) -> TokenStream {
let payload_str = match syn::parse_macro_input!(tokens as Lit) {
Lit::Str(st) => st.value(),
_ => panic!("Expected a string literal"),
};
let payload_bytes = payload_str.as_bytes();
let payload_len = payload_bytes.len();
let payload_len_str = payload_len.to_string();
let payload_len_bytes = payload_len_str.as_bytes();
let mut processed = quote! {
b'!',
};
for byte in payload_len_bytes {
processed = quote! {
#processed
#byte,
};
}
processed = quote! {
#processed
b'\n',
};
for byte in payload_bytes {
processed = quote! {
#processed
#byte,
}
}
processed = quote! {
[#processed
b'\n',]
};
processed.into()
}
#[proc_macro]
/// Get a compile time respcode/respstring slice. For example, if you pass: "Unknown action",
/// it will return: `!14\nUnknown Action\n`
pub fn compiled_eresp_bytes(tokens: TokenStream) -> TokenStream {
let ret = compiled_eresp_array(tokens);
let ret = syn::parse_macro_input!(ret as syn::Expr);
quote! {
&#ret
}
.into()
}

Loading…
Cancel
Save