Add `VALUEAT` and `LIMIT` subactions to `lget`

next
Sayan Nandan 3 years ago
parent 0e8d60df0a
commit 5238298ac4

@ -29,9 +29,12 @@ use crate::corestore::Data;
use crate::dbnet::connection::prelude::*;
use crate::kvengine::listmap::LockedVec;
use crate::kvengine::KVTable;
use crate::resp::writer;
use crate::resp::writer::TypedArrayWriter;
const LEN: &[u8] = "LEN".as_bytes();
const LIMIT: &[u8] = "LIMIT".as_bytes();
const VALUEAT: &[u8] = "VALUEAT".as_bytes();
macro_rules! listmap {
($tbl:expr, $con:expr) => {
@ -42,6 +45,17 @@ macro_rules! listmap {
};
}
macro_rules! writelist {
($con:expr, $listmap:expr, $items:expr) => {
let mut typed_array_writer =
unsafe { TypedArrayWriter::new($con, $listmap.get_payload_tsymbol(), $items.len()) }
.await?;
for item in $items {
typed_array_writer.write_element(item).await?;
}
};
}
action! {
/// Handle an `LSET` query for the list model
/// Syntax: `LSET <listname> <values ...>`
@ -80,6 +94,14 @@ action! {
// get the list name
let listname = unsafe { act.next_unchecked() };
// now let us see what we need to do
macro_rules! get_numeric_count {
() => {
match unsafe { String::from_utf8_lossy(act.next_unchecked()) }.parse::<usize>() {
Ok(int) => int,
Err(_) => return conwrite!(con, groups::WRONGTYPE_ERR),
}
};
}
match act.next_uppercase().as_ref() {
None => {
// just return everything in the list
@ -88,12 +110,7 @@ action! {
} else {
return conwrite!(con, groups::NIL);
};
let mut typed_array_writer = unsafe {
TypedArrayWriter::new(con, listmap.get_payload_tsymbol(), items.len())
}.await?;
for item in items {
typed_array_writer.write_element(item).await?;
}
writelist!(con, listmap, items);
}
Some(subaction) => {
match subaction.as_ref() {
@ -104,6 +121,41 @@ action! {
conwrite!(con, groups::NIL)?;
}
}
LIMIT => {
err_if_len_is!(act, con, not 1);
let count = get_numeric_count!();
let items = if let Some(keys) = listmap.get_cloned(listname, count) {
keys
} else {
return conwrite!(con, groups::NIL);
};
writelist!(con, listmap, items);
}
VALUEAT => {
err_if_len_is!(act, con, not 1);
let idx = get_numeric_count!();
let maybe_value = listmap.get(listname).map(|list| {
let readlist = list.read();
let get = readlist.get(idx).cloned();
get
});
match maybe_value {
Some(Some(value)) => {
unsafe {
// tsymbol is verified
writer::write_raw_mono(con, listmap.get_payload_tsymbol(), &value).await?;
}
},
Some(None) => {
// bad index
conwrite!(con, groups::LISTMAP_BAD_INDEX)?;
},
None => {
// not found
conwrite!(con, groups::NIL)?;
}
}
}
_ => conwrite!(con, groups::UNKNOWN_ACTION)?,
}
}

@ -91,6 +91,9 @@ impl KVEListMap {
pub fn {borrow: Data} get(self: &Self, key: &Q) -> Option<Vecref<'_>> {
self.base.get(key)
}
pub fn {borrow: Data} get_cloned(self: &Self, key: &Q, count: usize) -> Option<Vec<Data>> {
self.base.get(key).map(|v| v.read().iter().take(count).cloned().collect())
}
}
/// Create and add a new list to the map
pub fn add_list(&self, listname: Data) -> Option<bool> {

@ -101,6 +101,8 @@ pub mod groups {
pub const KEYSPACE_NOT_EMPTY: &[u8] = "!18\nkeyspace-not-empty\n".as_bytes();
/// 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();
/// The index for the provided list was non-existent
pub const LISTMAP_BAD_INDEX: &[u8] = "!9\nbad-list-index\n".as_bytes();
}
pub mod full_responses {

Loading…
Cancel
Save