123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- use crate::{
- check_arg, connection::Connection, error::Error, value::bytes_to_number, value::Value,
- };
- use bytes::Bytes;
- use rand::Rng;
- use std::{
- collections::{BTreeMap, HashMap},
- convert::TryFrom,
- ops::AddAssign,
- str::FromStr,
- };
- pub fn hdel(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- conn.db().get_map(
- &args[1],
- |v| match v {
- Value::Hash(h) => {
- let mut h = h.write();
- let mut total: i64 = 0;
- for key in (&args[2..]).iter() {
- if h.remove(key).is_some() {
- total += 1;
- }
- }
- Ok(total.into())
- }
- _ => Err(Error::WrongType),
- },
- || Ok(0_i64.into()),
- )
- }
- pub fn hexists(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => Ok(if h.read().get(&args[2]).is_some() {
- 1_i64.into()
- } else {
- 0_i64.into()
- }),
- Value::Null => Ok(0_i64.into()),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hget(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => Ok(if let Some(v) = h.read().get(&args[2]) {
- Value::Blob(v.clone())
- } else {
- Value::Null
- }),
- Value::Null => Ok(Value::Null),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hgetall(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => {
- let mut ret = vec![];
- for (key, value) in h.read().iter() {
- ret.push(Value::Blob(key.clone()));
- ret.push(Value::Blob(value.clone()));
- }
- Ok(ret.into())
- }
- Value::Null => Ok(Value::Array(vec![])),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hincrby<
- T: ToString + FromStr + AddAssign + for<'a> TryFrom<&'a Value, Error = Error> + Into<Value> + Copy,
- >(
- conn: &Connection,
- args: &[Bytes],
- ) -> Result<Value, Error> {
- conn.db().get_map(
- &args[1],
- |v| match v {
- Value::Hash(h) => {
- let mut incr_by: T = bytes_to_number(&args[3])?;
- let mut h = h.write();
- if let Some(n) = h.get(&args[2]) {
- incr_by += bytes_to_number(n)?;
- }
- h.insert(args[2].clone(), incr_by.to_string().into());
- Ok(incr_by.into())
- }
- _ => Err(Error::WrongType),
- },
- || {
- let incr_by: T = bytes_to_number(&args[3])?;
- #[allow(clippy::mutable_key_type)]
- let mut h = HashMap::new();
- h.insert(args[2].clone(), incr_by.to_string().into());
- conn.db().set(&args[1], h.into(), None);
- Ok(incr_by.into())
- },
- )
- }
- pub fn hkeys(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => {
- let mut ret = vec![];
- for key in h.read().keys() {
- ret.push(Value::Blob(key.clone()));
- }
- Ok(ret.into())
- }
- Value::Null => Ok(Value::Array(vec![])),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hlen(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => Ok((h.read().len() as i64).into()),
- Value::Null => Ok(0_i64.into()),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hmget(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => {
- let h = h.read();
- Ok((&args[2..])
- .iter()
- .map(|key| {
- if let Some(value) = h.get(key) {
- Value::Blob(value.clone())
- } else {
- Value::Null
- }
- })
- .collect::<Vec<Value>>()
- .into())
- }
- Value::Null => Ok(Value::Array(vec![])),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hrandfield(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- let (count, with_values) = match args.len() {
- 2 => (None, false),
- 3 => (Some(bytes_to_number::<i64>(&args[2])?), false),
- 4 => {
- if !(check_arg!(args, 3, "WITHVALUES")) {
- return Err(Error::Syntax);
- }
- (Some(bytes_to_number::<i64>(&args[2])?), true)
- }
- _ => return Err(Error::InvalidArgsCount("hrandfield".to_owned())),
- };
- let (count, single, repeat) = if let Some(count) = count {
- if count > 0 {
- (count, false, 1)
- } else {
- (count.abs(), false, count.abs())
- }
- } else {
- (1, true, 1)
- };
- match conn.db().get(&args[1]) {
- Value::Hash(h) => {
- let mut ret = vec![];
- let mut i = 0;
- let mut rand_sorted = BTreeMap::new();
- let mut rng = rand::thread_rng();
- let h = h.read();
- for _ in 0..repeat {
- for (key, value) in h.iter() {
- let rand = rng.gen::<u64>();
- rand_sorted.insert((rand, i), (key, value));
- i += 1;
- }
- }
- i = 0;
- for val in rand_sorted.values() {
- if single {
- return Ok(Value::Blob(val.0.clone()));
- }
- if i == count {
- break;
- }
- ret.push(Value::Blob(val.0.clone()));
- if with_values {
- ret.push(Value::Blob(val.1.clone()));
- }
- i += 1;
- }
- Ok(ret.into())
- }
- Value::Null => Ok(Value::Array(vec![])),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hset(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- if args.len() % 2 == 1 {
- return Err(Error::InvalidArgsCount("hset".to_owned()));
- }
- conn.db().get_map(
- &args[1],
- |v| match v {
- Value::Hash(h) => {
- let mut h = h.write();
- let mut e: i64 = 0;
- for i in (2..args.len()).step_by(2) {
- if h.insert(args[i].clone(), args[i + 1].clone()).is_none() {
- e += 1;
- }
- }
- Ok(e.into())
- }
- _ => Err(Error::WrongType),
- },
- || {
- #[allow(clippy::mutable_key_type)]
- let mut h = HashMap::new();
- for i in (2..args.len()).step_by(2) {
- h.insert(args[i].clone(), args[i + 1].clone());
- }
- let len = h.len() as i64;
- conn.db().set(&args[1], h.into(), None);
- Ok(len.into())
- },
- )
- }
- pub fn hsetnx(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- conn.db().get_map(
- &args[1],
- |v| match v {
- Value::Hash(h) => {
- let mut h = h.write();
- if h.get(&args[2]).is_some() {
- Ok(0_i64.into())
- } else {
- h.insert(args[2].clone(), args[3].clone());
- Ok(1_i64.into())
- }
- }
- _ => Err(Error::WrongType),
- },
- || {
- #[allow(clippy::mutable_key_type)]
- let mut h = HashMap::new();
- for i in (2..args.len()).step_by(2) {
- h.insert(args[i].clone(), args[i + 1].clone());
- }
- let len = h.len() as i64;
- conn.db().set(&args[1], h.into(), None);
- Ok(len.into())
- },
- )
- }
- pub fn hstrlen(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => Ok(if let Some(v) = h.read().get(&args[2]) {
- (v.len() as i64).into()
- } else {
- 0_i64.into()
- }),
- Value::Null => Ok(0_i64.into()),
- _ => Err(Error::WrongType),
- }
- }
- pub fn hvals(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {
- match conn.db().get(&args[1]) {
- Value::Hash(h) => {
- let mut ret = vec![];
- for value in h.read().values() {
- ret.push(Value::Blob(value.clone()));
- }
- Ok(ret.into())
- }
- Value::Null => Ok(Value::Array(vec![])),
- _ => Err(Error::WrongType),
- }
- }
|