| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741 | use crate::{    check_arg, connection::Connection, error::Error, value::bytes_to_number, value::checksum,    value::Value,};use bytes::Bytes;use std::collections::VecDeque;use tokio::time::{sleep, Duration, Instant};#[allow(clippy::needless_range_loop)]fn remove_element(    conn: &Connection,    key: &Bytes,    count: usize,    front: bool,) -> Result<Value, Error> {    conn.db().get_map_or(        key,        |v| match v {            Value::List(x) => {                let mut x = x.write();                if count == 0 {                    // Return a single element                    return Ok((if front { x.pop_front() } else { x.pop_back() })                        .map_or(Value::Null, |x| x.clone_value()));                }                let mut ret = vec![None; count];                for i in 0..count {                    if front {                        ret[i] = x.pop_front();                    } else {                        ret[i] = x.pop_back();                    }                }                let ret: Vec<Value> = ret                    .iter()                    .filter(|v| v.is_some())                    .map(|x| x.as_ref().unwrap().clone_value())                    .collect();                Ok(if ret.is_empty() {                    Value::Null                } else {                    ret.into()                })            }            _ => Err(Error::WrongType),        },        || Ok(Value::Null),    )}pub async fn blpop(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let timeout = Instant::now() + Duration::from_secs(bytes_to_number(&args[args.len() - 1])?);    let len = args.len() - 1;    loop {        for key in args[1..len].iter() {            match remove_element(conn, key, 0, true)? {                Value::Null => (),                n => return Ok(vec![Value::Blob(key.clone()), n].into()),            };        }        if Instant::now() >= timeout {            break;        }        sleep(Duration::from_millis(100)).await;    }    Ok(Value::Null)}pub async fn brpop(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let timeout = Instant::now() + Duration::from_secs(bytes_to_number(&args[args.len() - 1])?);    let len = args.len() - 1;    loop {        for key in args[1..len].iter() {            match remove_element(conn, key, 0, false)? {                Value::Null => (),                n => return Ok(vec![Value::Blob(key.clone()), n].into()),            };        }        if Instant::now() >= timeout {            break;        }        sleep(Duration::from_millis(100)).await;    }    Ok(Value::Null)}pub async fn lindex(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    conn.db().get_map_or(        &args[1],        |v| match v {            Value::List(x) => {                let mut index: i64 = bytes_to_number(&args[2])?;                let x = x.read();                if index < 0 {                    index += x.len() as i64;                }                Ok(x.get(index as usize)                    .map_or(Value::Null, |x| x.clone_value()))            }            _ => Err(Error::WrongType),        },        || Ok(0.into()),    )}pub async fn llen(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    conn.db().get_map_or(        &args[1],        |v| match v {            Value::List(x) => Ok((x.read().len() as i64).into()),            _ => Err(Error::WrongType),        },        || Ok(0.into()),    )}pub async fn lpop(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let count = if args.len() > 2 {        bytes_to_number(&args[2])?    } else {        0    };    remove_element(conn, &args[1], count, true)}pub async fn lpush(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let is_push_x = check_arg!(args, 0, "LPUSHX");    conn.db().get_map_or(        &args[1],        |v| match v {            Value::List(x) => {                let mut x = x.write();                for val in args.iter().skip(2) {                    x.push_front(checksum::Value::new(val.clone()));                }                Ok((x.len() as i64).into())            }            _ => Err(Error::WrongType),        },        || {            if is_push_x {                return Ok(0.into());            }            let mut h = VecDeque::new();            for val in args.iter().skip(2) {                h.push_front(checksum::Value::new(val.clone()));            }            let len = h.len() as i64;            conn.db().set(&args[1], h.into(), None);            Ok(len.into())        },    )}pub async fn lrange(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    conn.db().get_map_or(        &args[1],        |v| match v {            Value::List(x) => {                let mut start: i64 = bytes_to_number(&args[2])?;                let mut end: i64 = bytes_to_number(&args[3])?;                let mut ret = vec![];                let x = x.read();                if start < 0 {                    start += x.len() as i64;                }                if end < 0 {                    end += x.len() as i64;                }                for (i, val) in x.iter().enumerate() {                    if i >= start as usize && i <= end as usize {                        ret.push(val.clone_value());                    }                }                Ok(ret.into())            }            _ => Err(Error::WrongType),        },        || Ok(Value::Array(vec![])),    )}pub async fn rpop(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let count = if args.len() > 2 {        bytes_to_number(&args[2])?    } else {        0    };    remove_element(conn, &args[1], count, false)}pub async fn rpush(conn: &Connection, args: &[Bytes]) -> Result<Value, Error> {    let is_push_x = check_arg!(args, 0, "RPUSHX");    conn.db().get_map_or(        &args[1],        |v| match v {            Value::List(x) => {                let mut x = x.write();                for val in args.iter().skip(2) {                    x.push_back(checksum::Value::new(val.clone()));                }                Ok((x.len() as i64).into())            }            _ => Err(Error::WrongType),        },        || {            if is_push_x {                return Ok(0.into());            }            let mut h = VecDeque::new();            for val in args.iter().skip(2) {                h.push_back(checksum::Value::new(val.clone()));            }            let len = h.len() as i64;            conn.db().set(&args[1], h.into(), None);            Ok(len.into())        },    )}#[cfg(test)]mod test {    use crate::{        cmd::test::{create_connection, run_command},        value::Value,    };    use tokio::time::{sleep, Duration, Instant};    #[tokio::test]    async fn blpop_no_waiting() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await,        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("foo".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["blpop", "foo", "1"]).await        );    }    #[tokio::test]    async fn blpop_timeout() {        let c = create_connection();        let x = Instant::now();        assert_eq!(            Ok(Value::Null),            run_command(&c, &["blpop", "foobar", "1"]).await        );        assert!(Instant::now() - x > Duration::from_millis(1000));    }    #[tokio::test]    async fn blpop_wait_insert() {        let c = create_connection();        let x = Instant::now();        // Query command that will block connection until some data is inserted        // to foobar, foo, bar or the 5 seconds timeout happens.        //        // We are issuing the command, sleeping a little bit then adding data to        // foobar, before actually waiting on the result.        let waiting = run_command(&c, &["blpop", "foobar", "foo", "bar", "5"]);        // Sleep 1 second before inserting new data        sleep(Duration::from_millis(1000)).await;        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await,        );        // Read the output of the first blpop command now.        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("foo".into()),                Value::Blob("5".into()),            ])),            waiting.await        );        assert!(Instant::now() - x > Duration::from_millis(1000));        assert!(Instant::now() - x < Duration::from_millis(5000));    }    #[tokio::test]    async fn brpop_no_waiting() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await,        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("foo".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["brpop", "foo", "1"]).await        );    }    #[tokio::test]    async fn brpop_timeout() {        let c = create_connection();        let x = Instant::now();        assert_eq!(            Ok(Value::Null),            run_command(&c, &["brpop", "foobar", "1"]).await        );        assert!(Instant::now() - x > Duration::from_millis(1000));    }    #[tokio::test]    async fn brpop_wait_insert() {        let c = create_connection();        let x = Instant::now();        // Query command that will block connection until some data is inserted        // to foobar, foo, bar or the 5 seconds timeout happens.        //        // We are issuing the command, sleeping a little bit then adding data to        // foobar, before actually waiting on the result.        let waiting = run_command(&c, &["brpop", "foobar", "foo", "bar", "5"]);        // Sleep 1 second before inserting new data        sleep(Duration::from_millis(1000)).await;        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await,        );        // Read the output of the first blpop command now.        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("foo".into()),                Value::Blob("5".into()),            ])),            waiting.await        );        assert!(Instant::now() - x > Duration::from_millis(1000));        assert!(Instant::now() - x < Duration::from_millis(5000));    }    #[tokio::test]    async fn lindex() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("5".into()),                Value::Blob("4".into()),                Value::Blob("3".into()),                Value::Blob("2".into()),                Value::Blob("1".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Blob("5".into())),            run_command(&c, &["lindex", "foo", "0"]).await        );        assert_eq!(            Ok(Value::Blob("1".into())),            run_command(&c, &["lindex", "foo", "-1"]).await        );        assert_eq!(            Ok(Value::Null),            run_command(&c, &["lindex", "foo", "-100"]).await        );        assert_eq!(            Ok(Value::Null),            run_command(&c, &["lindex", "foo", "100"]).await        );    }    #[tokio::test]    async fn llen() {        let c = create_connection();        assert_eq!(            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await,            run_command(&c, &["llen", "foo"]).await        );        assert_eq!(            Ok(Value::Integer(0)),            run_command(&c, &["llen", "foobar"]).await        );    }    #[tokio::test]    async fn lpop() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await,        );        assert_eq!(            Ok(Value::Blob("5".into())),            run_command(&c, &["lpop", "foo"]).await        );        assert_eq!(            Ok(Value::Array(vec![Value::Blob("4".into())])),            run_command(&c, &["lpop", "foo", "1"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("3".into()),                Value::Blob("2".into()),                Value::Blob("1".into()),            ])),            run_command(&c, &["lpop", "foo", "55"]).await        );        assert_eq!(            Ok(Value::Null),            run_command(&c, &["lpop", "foo", "55"]).await        );        assert_eq!(Ok(Value::Null), run_command(&c, &["lpop", "foo"]).await);        assert_eq!(            Ok(Value::Integer(0)),            run_command(&c, &["llen", "foobar"]).await        );    }    #[tokio::test]    async fn lpush() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["lpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("5".into()),                Value::Blob("4".into()),                Value::Blob("3".into()),                Value::Blob("2".into()),                Value::Blob("1".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Integer(10)),            run_command(&c, &["lpush", "foo", "6", "7", "8", "9", "10"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("10".into()),                Value::Blob("9".into()),                Value::Blob("8".into()),                Value::Blob("7".into()),                Value::Blob("6".into()),                Value::Blob("5".into()),                Value::Blob("4".into()),                Value::Blob("3".into()),                Value::Blob("2".into()),                Value::Blob("1".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );    }    #[tokio::test]    async fn lpush_simple() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(1)),            run_command(&c, &["lpush", "foo", "world"]).await        );        assert_eq!(            Ok(Value::Integer(2)),            run_command(&c, &["lpush", "foo", "hello"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("hello".into()),                Value::Blob("world".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );    }    #[tokio::test]    async fn rpop() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Blob("5".into())),            run_command(&c, &["rpop", "foo"]).await        );        assert_eq!(            Ok(Value::Array(vec![Value::Blob("4".into())])),            run_command(&c, &["rpop", "foo", "1"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("3".into()),                Value::Blob("2".into()),                Value::Blob("1".into()),            ])),            run_command(&c, &["rpop", "foo", "55"]).await        );        assert_eq!(            Ok(Value::Null),            run_command(&c, &["rpop", "foo", "55"]).await        );        assert_eq!(Ok(Value::Null), run_command(&c, &["rpop", "foo"]).await);        assert_eq!(            Ok(Value::Integer(0)),            run_command(&c, &["llen", "foobar"]).await        );    }    #[tokio::test]    async fn rpush_simple() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(1)),            run_command(&c, &["rpush", "foo", "world"]).await        );        assert_eq!(            Ok(Value::Integer(2)),            run_command(&c, &["rpush", "foo", "hello"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("world".into()),                Value::Blob("hello".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );    }    #[tokio::test]    async fn lrange() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-2"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("4".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["lrange", "foo", "-2", "-1"]).await        );        assert_eq!(            Ok(Value::Array(vec![Value::Blob("3".into()),])),            run_command(&c, &["lrange", "foo", "-3", "-3"]).await        );    }    #[tokio::test]    async fn rpush() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Integer(10)),            run_command(&c, &["rpush", "foo", "6", "7", "8", "9", "10"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),                Value::Blob("5".into()),                Value::Blob("6".into()),                Value::Blob("7".into()),                Value::Blob("8".into()),                Value::Blob("9".into()),                Value::Blob("10".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );    }    #[tokio::test]    async fn rpushx() {        let c = create_connection();        assert_eq!(            Ok(Value::Integer(5)),            run_command(&c, &["rpush", "foo", "1", "2", "3", "4", "5"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),                Value::Blob("5".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Integer(10)),            run_command(&c, &["rpushx", "foo", "6", "7", "8", "9", "10"]).await        );        assert_eq!(            Ok(Value::Array(vec![                Value::Blob("1".into()),                Value::Blob("2".into()),                Value::Blob("3".into()),                Value::Blob("4".into()),                Value::Blob("5".into()),                Value::Blob("6".into()),                Value::Blob("7".into()),                Value::Blob("8".into()),                Value::Blob("9".into()),                Value::Blob("10".into()),            ])),            run_command(&c, &["lrange", "foo", "0", "-1"]).await        );        assert_eq!(            Ok(Value::Integer(0)),            run_command(&c, &["rpushx", "foobar", "6", "7", "8", "9", "10"]).await        );    }}
 |