From 0e88b3fe316fc8fb490c59de62b529b82dfe93a3 Mon Sep 17 00:00:00 2001 From: Alec Embke Date: Fri, 17 Sep 2021 18:31:17 -0700 Subject: [PATCH] 4.0.0 (#6) * Generic response types --- CHANGELOG.md | 10 + Cargo.toml | 2 +- README.md | 14 +- bin/pipeline_test/src/main.rs | 2 +- examples/basic.rs | 10 +- examples/blocking.rs | 14 +- examples/scan.rs | 2 +- examples/tls.rs | 10 +- examples/transactions.rs | 17 +- src/client.rs | 871 +++++++++++++++++---------- src/error.rs | 23 +- src/lib.rs | 19 +- src/response.rs | 499 +++++++++++++++ src/types.rs | 143 ++++- tests/integration/geo/mod.rs | 34 +- tests/integration/hashes/mod.rs | 149 +++-- tests/integration/hyperloglog/mod.rs | 38 +- tests/integration/keys/mod.rs | 191 +++--- tests/integration/lists/mod.rs | 236 ++++---- tests/integration/lua/mod.rs | 51 +- tests/integration/memory/mod.rs | 2 +- tests/integration/multi/mod.rs | 31 +- tests/integration/other/mod.rs | 16 +- tests/integration/pubsub/mod.rs | 8 +- tests/integration/server/mod.rs | 24 +- tests/integration/sets/mod.rs | 185 +++--- tests/integration/sorted_sets/mod.rs | 302 +++++----- tests/integration/utils.rs | 13 +- 28 files changed, 1895 insertions(+), 1021 deletions(-) create mode 100644 src/response.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 135b83c5..682bc811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## 4.0.0 + +* Add generic response interface. +* Add tests + +## 3.0.0 + +See below. + ## 3.0.0-beta.4 * Add support for the `MONITOR` command. diff --git a/Cargo.toml b/Cargo.toml index 680c8bfa..2e48d1b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fred" -version = "3.0.0-beta.4" +version = "4.0.0" authors = ["Alec Embke "] edition = "2018" description = "An async Redis client for Rust built on Futures and Tokio." diff --git a/README.md b/README.md index 1cc27667..d4d82cf2 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,18 @@ async fn main() -> Result<(), RedisError> { let _ = client.connect(Some(policy)); // wait for the client to connect let _ = client.wait_for_connect().await?; + let _ = client.flushall(false).await?; + + let foo: Option = client.get("foo").await?; + println!("Foo: {:?}", foo); + assert_eq!(foo, None); - println!("Foo: {:?}", client.get("foo").await?); - let _ = client.set("foo", "bar", None, None, false).await?; - println!("Foo: {:?}", client.get("foo".to_owned()).await?); + let _: () = client.set("foo", "bar", None, None, false).await?; + // or use turbofish to declare types + println!("Foo: {:?}", client.get("foo").await?); + // or use a lower level interface for responses to defer parsing, etc + let foo: RedisValue = client.get("foo").await?; + assert_eq!(foo.as_str().unwrap(), "bar"); let _ = client.quit().await?; Ok(()) diff --git a/bin/pipeline_test/src/main.rs b/bin/pipeline_test/src/main.rs index 6de80652..2d304559 100644 --- a/bin/pipeline_test/src/main.rs +++ b/bin/pipeline_test/src/main.rs @@ -144,7 +144,7 @@ fn spawn_client_task( tokio::spawn(async move { while utils::incr_atomic(&counter) < argv.count { - let _ = client.incr(TEST_KEY).await?; + let _: () = client.incr(TEST_KEY).await?; } Ok(()) diff --git a/examples/basic.rs b/examples/basic.rs index 5a64969d..baab16ea 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -44,14 +44,16 @@ async fn main() -> Result<(), RedisError> { let _ = client.connect(Some(policy)); let _ = client.wait_for_connect().await?; - println!("Foo: {:?}", client.get("foo").await?); + // declare types on response values + let foo: Option = client.get("foo").await?; + println!("Foo: {:?}", foo); + let _ = client .set("foo", "bar", Some(Expiration::EX(1)), Some(SetOptions::NX), false) .await?; - println!("Foo: {:?}", client.get("foo").await?); - sleep(Duration::from_millis(1000)).await; - println!("Foo: {:?}", client.get("foo").await?); + // or use turbofish. the first type is always the response type. + println!("Foo: {:?}", client.get::("foo").await?); let _ = client.quit().await?; Ok(()) diff --git a/examples/blocking.rs b/examples/blocking.rs index 21ffee5b..9eeea715 100644 --- a/examples/blocking.rs +++ b/examples/blocking.rs @@ -2,10 +2,12 @@ use fred::prelude::*; use std::time::Duration; use tokio::time::sleep; -static COUNT: usize = 50; +static COUNT: i64 = 50; #[tokio::main] async fn main() -> Result<(), RedisError> { + pretty_env_logger::init(); + let config = RedisConfig::default(); let publisher_client = RedisClient::new(config.clone()); let subscriber_client = RedisClient::new(config.clone()); @@ -16,15 +18,15 @@ async fn main() -> Result<(), RedisError> { let _ = subscriber_client.wait_for_connect().await?; let subscriber_jh = tokio::spawn(async move { - while let Ok(result) = subscriber_client.blpop("foo", 5.0).await { - println!("Blocking pop result: {:?}", result); + while let Ok((key, value)) = subscriber_client.blpop::<(String, i64), _>("foo", 5.0).await { + println!("Blocking pop result on {}: {}", key, value); } - Ok::<_, RedisError>(()) + Ok::<(), RedisError>(()) }); - for _ in 0..COUNT { - let _ = publisher_client.rpush("foo", "bar").await?; + for idx in 0..COUNT { + let _ = publisher_client.rpush("foo", idx).await?; sleep(Duration::from_millis(1000)).await; } diff --git a/examples/scan.rs b/examples/scan.rs index e9733d30..cf531b95 100644 --- a/examples/scan.rs +++ b/examples/scan.rs @@ -38,7 +38,7 @@ async fn main() -> Result<(), RedisError> { let client = page.create_client(); for key in keys.into_iter() { - let value = client.get(&key).await?; + let value: RedisValue = client.get(&key).await?; println!("Scanned {} -> {:?}", key.as_str_lossy(), value); buffer.push((key, value)); } diff --git a/examples/tls.rs b/examples/tls.rs index fe9c2c91..79ba8a31 100644 --- a/examples/tls.rs +++ b/examples/tls.rs @@ -15,17 +15,9 @@ async fn main() -> Result<(), RedisError> { }), ..RedisConfig::default() }; - let policy = ReconnectPolicy::new_exponential(0, 100, 30_000, 2); let client = RedisClient::new(config); - tokio::spawn(client.on_error().for_each(|e| async move { - println!("Client received connection error: {:?}", e); - })); - tokio::spawn(client.on_reconnect().for_each(|client| async move { - println!("Client {} reconnected.", client.id()); - })); - - let jh = client.connect(Some(policy)); + let jh = client.connect(None); if let Err(error) = client.wait_for_connect().await { println!("Client failed to connect with error: {:?}", error); } diff --git a/examples/transactions.rs b/examples/transactions.rs index 43817018..bfd9dfc4 100644 --- a/examples/transactions.rs +++ b/examples/transactions.rs @@ -5,23 +5,20 @@ async fn main() -> Result<(), RedisError> { let config = RedisConfig::default(); let client = RedisClient::new(config); - let jh = client.connect(None); + let _ = client.connect(None); let _ = client.wait_for_connect().await?; - - // a special function to clear all data in a cluster - let _ = client.flushall_cluster().await?; + let _ = client.flushall(false).await?; let trx = client.multi(true).await?; - let res1 = trx.get("foo").await?; + let res1: RedisValue = trx.get("foo").await?; assert!(res1.is_queued()); - let res2 = trx.set("foo", "bar", None, None, false).await?; + let res2: RedisValue = trx.set("foo", "bar", None, None, false).await?; assert!(res2.is_queued()); - let res3 = trx.get("foo").await?; + let res3: RedisValue = trx.get("foo").await?; assert!(res3.is_queued()); - if let RedisValue::Array(values) = trx.exec().await? { - println!("Transaction results: {:?}", values); - } + let values: (Option, (), String) = trx.exec().await?; + println!("Transaction results: {:?}", values); let _ = client.quit().await?; Ok(()) diff --git a/src/client.rs b/src/client.rs index bb055476..4bf9b793 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,6 +5,7 @@ use crate::metrics::*; use crate::multiplexer::commands as multiplexer_commands; use crate::multiplexer::utils as multiplexer_utils; use crate::protocol::types::RedisCommand; +use crate::response::RedisResponse; use crate::types::*; use crate::utils; use futures::Stream; @@ -74,9 +75,12 @@ impl TransactionClient { /// If the underlying connection closes while a transaction is in process the client will abort the transaction by /// returning a `Canceled` error to the caller of any pending intermediate command, as well as this one. It's up to /// the caller to retry transactions as needed. - pub async fn exec(mut self) -> Result { + pub async fn exec(mut self) -> Result + where + R: RedisResponse, + { self.finished = true; - commands::server::exec(&self.client.inner).await + commands::server::exec(&self.client.inner).await?.convert() } /// Flushes all previously queued commands in a transaction and restores the connection state to normal. @@ -413,24 +417,33 @@ impl RedisClient { /// Instruct Redis to start an Append Only File rewrite process. /// /// - pub async fn bgrewriteaof(&self) -> Result { + pub async fn bgrewriteaof(&self) -> Result + where + R: RedisResponse, + { utils::disallow_during_transaction(&self.inner)?; - commands::server::bgrewriteaof(&self.inner).await + commands::server::bgrewriteaof(&self.inner).await?.convert() } /// Save the DB in background. /// /// - pub async fn bgsave(&self) -> Result { + pub async fn bgsave(&self) -> Result + where + R: RedisResponse, + { utils::disallow_during_transaction(&self.inner)?; - commands::server::bgsave(&self.inner).await + commands::server::bgsave(&self.inner).await?.convert() } /// Return the number of keys in the selected database. /// /// - pub async fn dbsize(&self) -> Result { - commands::server::dbsize(&self.inner).await + pub async fn dbsize(&self) -> Result + where + R: RedisResponse, + { + commands::server::dbsize(&self.inner).await?.convert() } /// Run a custom command that is not yet supported via another interface on this client. This is most useful when interacting with third party modules or extensions. @@ -448,12 +461,15 @@ impl RedisClient { /// Callers that find themselves using this interface for commands that are not a part of a third party extension should file an issue /// to add the command to the list of supported commands. This interface should be used with caution as it may break the automatic pipeline /// features in the client if command flags are not properly configured. - pub async fn custom(&self, cmd: CustomCommand, args: Vec) -> Result + pub async fn custom(&self, cmd: CustomCommand, args: Vec) -> Result where + R: RedisResponse, T: TryInto, T::Error: Into, { - commands::server::custom(&self.inner, cmd, utils::try_into_vec(args)?).await + commands::server::custom(&self.inner, cmd, utils::try_into_vec(args)?) + .await? + .convert() } /// Subscribe to a channel on the PubSub interface, returning the number of channels to which the client is subscribed. @@ -506,13 +522,16 @@ impl RedisClient { /// Publish a message on the PubSub interface, returning the number of clients that received the message. /// /// - pub async fn publish(&self, channel: S, message: V) -> Result + pub async fn publish(&self, channel: S, message: V) -> Result where + R: RedisResponse, S: Into, V: TryInto, V::Error: Into, { - commands::pubsub::publish(&self.inner, channel, to!(message)?).await + commands::pubsub::publish(&self.inner, channel, to!(message)?) + .await? + .convert() } /// Enter a MULTI block, executing subsequent commands as a transaction. @@ -594,8 +613,11 @@ impl RedisClient { /// Delete the keys in all databases. /// /// - pub async fn flushall(&self, r#async: bool) -> Result { - commands::server::flushall(&self.inner, r#async).await + pub async fn flushall(&self, r#async: bool) -> Result + where + R: RedisResponse, + { + commands::server::flushall(&self.inner, r#async).await?.convert() } /// Delete the keys on all nodes in the cluster. This is a special function that does not map directly to the Redis interface. @@ -610,22 +632,25 @@ impl RedisClient { /// Ping the Redis server. /// /// - pub async fn ping(&self) -> Result { - commands::server::ping(&self.inner).await + pub async fn ping(&self) -> Result<(), RedisError> { + commands::server::ping(&self.inner).await?.convert() } /// Select the database this client should use. /// /// - pub async fn select(&self, db: u8) -> Result { - commands::server::select(&self.inner, db).await + pub async fn select(&self, db: u8) -> Result<(), RedisError> { + commands::server::select(&self.inner, db).await?.convert() } /// Read info about the Redis server. /// /// - pub async fn info(&self, section: Option) -> Result { - commands::server::info(&self.inner, section).await + pub async fn info(&self, section: Option) -> Result + where + R: RedisResponse, + { + commands::server::info(&self.inner, section).await?.convert() } /// This command will start a coordinated failover between the currently-connected-to master and one of its replicas. @@ -645,8 +670,11 @@ impl RedisClient { /// Return the UNIX TIME of the last DB save executed with success. /// /// - pub async fn lastsave(&self) -> Result { - commands::server::lastsave(&self.inner).await + pub async fn lastsave(&self) -> Result + where + R: RedisResponse, + { + commands::server::lastsave(&self.inner).await?.convert() } // ------------- SLOWLOG ---------------- @@ -682,8 +710,11 @@ impl RedisClient { /// Note: Against a clustered deployment this will return the ID of a random connection. See [connection_ids](Self::connection_ids) for more information. /// /// - pub async fn client_id(&self) -> Result { - commands::client::client_id(&self.inner).await + pub async fn client_id(&self) -> Result + where + R: RedisResponse, + { + commands::client::client_id(&self.inner).await?.convert() } /// Read the connection IDs for the active connections to each server. @@ -701,36 +732,42 @@ impl RedisClient { /// The command returns information and statistics about the current client connection in a mostly human readable format. /// /// - pub async fn client_info(&self) -> Result { - commands::client::client_info(&self.inner).await + pub async fn client_info(&self) -> Result + where + R: RedisResponse, + { + commands::client::client_info(&self.inner).await?.convert() } /// Close a given connection or set of connections. /// /// - pub async fn client_kill(&self, filters: Vec) -> Result { - commands::client::client_kill(&self.inner, filters).await + pub async fn client_kill(&self, filters: Vec) -> Result + where + R: RedisResponse, + { + commands::client::client_kill(&self.inner, filters).await?.convert() } /// The CLIENT LIST command returns information and statistics about the client connections server in a mostly human readable format. /// /// - pub async fn client_list( - &self, - r#type: Option, - ids: Option>, - ) -> Result + pub async fn client_list(&self, r#type: Option, ids: Option>) -> Result where + R: RedisResponse, I: Into, { - commands::client::client_list(&self.inner, r#type, ids).await + commands::client::client_list(&self.inner, r#type, ids).await?.convert() } /// The CLIENT GETNAME returns the name of the current connection as set by CLIENT SETNAME. /// /// - pub async fn client_getname(&self) -> Result { - commands::client::client_getname(&self.inner).await + pub async fn client_getname(&self) -> Result + where + R: RedisResponse, + { + commands::client::client_getname(&self.inner).await?.convert() } /// Assign a name to the current connection. @@ -776,11 +813,12 @@ impl RedisClient { /// Note: this command is sent on a backchannel connection and will work even when the main connection is blocked. /// /// - pub async fn client_unblock(&self, id: S, flag: Option) -> Result + pub async fn client_unblock(&self, id: S, flag: Option) -> Result where + R: RedisResponse, S: Into, { - commands::client::client_unblock(&self.inner, id, flag).await + commands::client::client_unblock(&self.inner, id, flag).await?.convert() } /// A convenience function to unblock any blocked connection on this client. @@ -794,8 +832,11 @@ impl RedisClient { /// Advances the cluster config epoch. /// /// - pub async fn cluster_bumpepoch(&self) -> Result { - commands::cluster::cluster_bumpepoch(&self.inner).await + pub async fn cluster_bumpepoch(&self) -> Result + where + R: RedisResponse, + { + commands::cluster::cluster_bumpepoch(&self.inner).await?.convert() } /// Deletes all slots from a node. @@ -809,8 +850,11 @@ impl RedisClient { /// Returns the node's id. /// /// - pub async fn cluster_myid(&self) -> Result { - commands::cluster::cluster_myid(&self.inner).await + pub async fn cluster_myid(&self) -> Result + where + R: RedisResponse, + { + commands::cluster::cluster_myid(&self.inner).await?.convert() } /// Read the current cluster node configuration. @@ -818,8 +862,8 @@ impl RedisClient { /// Note: The client keeps a cached, parsed version of the cluster state in memory available at [cached_cluster_state](Self::cached_cluster_state). /// /// - pub async fn cluster_nodes(&self) -> Result { - commands::cluster::cluster_nodes(&self.inner).await + pub async fn cluster_nodes(&self) -> Result { + commands::cluster::cluster_nodes(&self.inner).await?.convert() } /// Forces a node to save the nodes.conf configuration on disk. @@ -860,18 +904,26 @@ impl RedisClient { /// The command returns the number of failure reports for the specified node. /// /// - pub async fn cluster_count_failure_reports(&self, node_id: S) -> Result + pub async fn cluster_count_failure_reports(&self, node_id: S) -> Result where + R: RedisResponse, S: Into, { - commands::cluster::cluster_count_failure_reports(&self.inner, node_id).await + commands::cluster::cluster_count_failure_reports(&self.inner, node_id) + .await? + .convert() } /// Returns the number of keys in the specified Redis Cluster hash slot. /// /// - pub async fn cluster_count_keys_in_slot(&self, slot: u16) -> Result { - commands::cluster::cluster_count_keys_in_slot(&self.inner, slot).await + pub async fn cluster_count_keys_in_slot(&self, slot: u16) -> Result + where + R: RedisResponse, + { + commands::cluster::cluster_count_keys_in_slot(&self.inner, slot) + .await? + .convert() } /// The CLUSTER DELSLOTS command asks a particular Redis Cluster node to forget which master is serving the hash slots specified as arguments. @@ -908,19 +960,25 @@ impl RedisClient { /// The command returns an array of keys names stored in the contacted node and hashing to the specified hash slot. /// /// - pub async fn cluster_get_keys_in_slot(&self, slot: u16, count: u64) -> Result { + pub async fn cluster_get_keys_in_slot(&self, slot: u16, count: u64) -> Result + where + R: RedisResponse, + { utils::disallow_during_transaction(&self.inner)?; - commands::cluster::cluster_get_keys_in_slot(&self.inner, slot, count).await + commands::cluster::cluster_get_keys_in_slot(&self.inner, slot, count) + .await? + .convert() } /// Returns an integer identifying the hash slot the specified key hashes to. /// /// - pub async fn cluster_keyslot(&self, key: K) -> Result + pub async fn cluster_keyslot(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::cluster::cluster_keyslot(&self.inner, key).await + commands::cluster::cluster_keyslot(&self.inner, key).await?.convert() } /// CLUSTER MEET is used in order to connect different Redis nodes with cluster support enabled, into a working cluster. @@ -949,11 +1007,13 @@ impl RedisClient { /// The command provides a list of replica nodes replicating from the specified master node. /// /// - pub async fn cluster_replicas(&self, node_id: S) -> Result + pub async fn cluster_replicas(&self, node_id: S) -> Result where S: Into, { - commands::cluster::cluster_replicas(&self.inner, node_id).await + commands::cluster::cluster_replicas(&self.inner, node_id) + .await? + .convert() } /// Reset a Redis Cluster node, in a more or less drastic way depending on the reset type, that can be hard or soft. Note that @@ -1005,12 +1065,13 @@ impl RedisClient { /// The CONFIG GET command is used to read the configuration parameters of a running Redis server. /// /// - pub async fn config_get(&self, parameter: S) -> Result + pub async fn config_get(&self, parameter: S) -> Result where + R: RedisResponse, S: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::config::config_get(&self.inner, parameter).await + commands::config::config_get(&self.inner, parameter).await?.convert() } /// The CONFIG SET command is used in order to reconfigure the server at run time without the need to restart Redis. @@ -1094,17 +1155,23 @@ impl RedisClient { /// The command shows the currently active ACL rules in the Redis server. /// /// - pub async fn acl_list(&self) -> Result { + pub async fn acl_list(&self) -> Result + where + R: RedisResponse, + { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_list(&self.inner).await + commands::acl::acl_list(&self.inner).await?.convert() } /// The command shows a list of all the usernames of the currently configured users in the Redis ACL system. /// /// - pub async fn acl_users(&self) -> Result { + pub async fn acl_users(&self) -> Result + where + R: RedisResponse, + { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_users(&self.inner).await + commands::acl::acl_users(&self.inner).await?.convert() } /// The command returns all the rules defined for an existing ACL user. @@ -1132,39 +1199,40 @@ impl RedisClient { /// Delete all the specified ACL users and terminate all the connections that are authenticated with such users. /// /// - pub async fn acl_deluser(&self, usernames: S) -> Result + pub async fn acl_deluser(&self, usernames: S) -> Result where + R: RedisResponse, S: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_deluser(&self.inner, usernames).await + commands::acl::acl_deluser(&self.inner, usernames).await?.convert() } /// The command shows the available ACL categories if called without arguments. If a category name is given, /// the command shows all the Redis commands in the specified category. /// /// - pub async fn acl_cat(&self, category: Option) -> Result + pub async fn acl_cat(&self, category: Option) -> Result, RedisError> where S: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_cat(&self.inner, category).await + commands::acl::acl_cat(&self.inner, category).await?.convert() } /// Generate a password with length `bits`, returning the password. - pub async fn acl_genpass(&self, bits: Option) -> Result { + pub async fn acl_genpass(&self, bits: Option) -> Result { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_genpass(&self.inner, bits).await + commands::acl::acl_genpass(&self.inner, bits).await?.convert() } /// Return the username the current connection is authenticated with. New connections are authenticated /// with the "default" user. /// /// - pub async fn acl_whoami(&self) -> Result { + pub async fn acl_whoami(&self) -> Result { utils::disallow_during_transaction(&self.inner)?; - commands::acl::acl_whoami(&self.inner).await + commands::acl::acl_whoami(&self.inner).await?.convert() } /// Read `count` recent ACL security events. @@ -1188,25 +1256,25 @@ impl RedisClient { /// Return a random key from the currently selected database. /// /// - pub async fn randomkey(&self) -> Result { - commands::keys::randomkey(&self.inner).await + pub async fn randomkey(&self) -> Result + where + R: RedisResponse, + { + commands::keys::randomkey(&self.inner).await?.convert() } /// This command copies the value stored at the source key to the destination key. /// /// - pub async fn copy( - &self, - source: S, - destination: D, - db: Option, - replace: bool, - ) -> Result + pub async fn copy(&self, source: S, destination: D, db: Option, replace: bool) -> Result where + R: RedisResponse, S: Into, D: Into, { - commands::keys::copy(&self.inner, source, destination, db, replace).await + commands::keys::copy(&self.inner, source, destination, db, replace) + .await? + .convert() } /// Serialize the value stored at `key` in a Redis-specific format and return it as bulk string. @@ -1241,31 +1309,35 @@ impl RedisClient { /// Set a value with optional NX|XX, EX|PX|EXAT|PXAT|KEEPTTL, and GET arguments. /// /// - pub async fn set( + pub async fn set( &self, key: K, value: V, expire: Option, options: Option, get: bool, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { let (key, value) = (key.into(), to!(value)?); - commands::keys::set(&self.inner, key, value, expire, options, get).await + commands::keys::set(&self.inner, key, value, expire, options, get) + .await? + .convert() } /// Read a value from the server. /// /// - pub async fn get(&self, key: K) -> Result + pub async fn get(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::get(&self.inner, key).await + commands::keys::get(&self.inner, key).await?.convert() } /// Returns the substring of the string value stored at `key` with offsets `start` and `end` (both inclusive). @@ -1273,23 +1345,27 @@ impl RedisClient { /// Note: Command formerly called SUBSTR in Redis verison <=2.0. /// /// - pub async fn getrange(&self, key: K, start: usize, end: usize) -> Result + pub async fn getrange(&self, key: K, start: usize, end: usize) -> Result where + R: RedisResponse, K: Into, { - commands::keys::getrange(&self.inner, key, start, end).await + commands::keys::getrange(&self.inner, key, start, end).await?.convert() } /// Overwrites part of the string stored at `key`, starting at the specified `offset`, for the entire length of `value`. /// /// - pub async fn setrange(&self, key: K, offset: u32, value: V) -> Result + pub async fn setrange(&self, key: K, offset: u32, value: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::keys::setrange(&self.inner, key, offset, to!(value)?).await + commands::keys::setrange(&self.inner, key, offset, to!(value)?) + .await? + .convert() } /// Atomically sets `key` to `value` and returns the old value stored at `key`. @@ -1297,33 +1373,36 @@ impl RedisClient { /// Returns an error if `key` does not hold string value. Returns nil if `key` does not exist. /// /// - pub async fn getset(&self, key: K, value: V) -> Result + pub async fn getset(&self, key: K, value: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::keys::getset(&self.inner, key, to!(value)?).await + commands::keys::getset(&self.inner, key, to!(value)?).await?.convert() } /// Get the value of key and delete the key. This command is similar to GET, except for the fact that it also deletes the key on success (if and only if the key's value type is a string). /// /// - pub async fn getdel(&self, key: K) -> Result + pub async fn getdel(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::getdel(&self.inner, key).await + commands::keys::getdel(&self.inner, key).await?.convert() } /// Returns the length of the string value stored at key. An error is returned when key holds a non-string value. /// /// - pub async fn strlen(&self, key: K) -> Result + pub async fn strlen(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::strlen(&self.inner, key).await + commands::keys::strlen(&self.inner, key).await?.convert() } /// Removes the specified keys. A key is ignored if it does not exist. @@ -1331,21 +1410,23 @@ impl RedisClient { /// Returns the number of keys removed. /// /// - pub async fn del(&self, keys: K) -> Result + pub async fn del(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::del(&self.inner, keys).await + commands::keys::del(&self.inner, keys).await?.convert() } /// Returns the values of all specified keys. For every key that does not hold a string value or does not exist, the special value nil is returned. /// /// - pub async fn mget(&self, keys: K) -> Result + pub async fn mget(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::mget(&self.inner, keys).await + commands::keys::mget(&self.inner, keys).await?.convert() } /// Sets the given keys to their respective values. @@ -1361,11 +1442,12 @@ impl RedisClient { /// Sets the given keys to their respective values. MSETNX will not perform any operation at all even if just a single key already exists. /// /// - pub async fn msetnx(&self, values: V) -> Result + pub async fn msetnx(&self, values: V) -> Result where + R: RedisResponse, V: Into, { - commands::keys::msetnx(&self.inner, values).await + commands::keys::msetnx(&self.inner, values).await?.convert() } /// Increments the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the operation. @@ -1373,11 +1455,12 @@ impl RedisClient { /// Returns an error if the value at key is of the wrong type. /// /// - pub async fn incr(&self, key: K) -> Result + pub async fn incr(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::incr(&self.inner, key).await + commands::keys::incr(&self.inner, key).await?.convert() } /// Increments the number stored at `key` by `val`. If the key does not exist, it is set to 0 before performing the operation. @@ -1385,11 +1468,12 @@ impl RedisClient { /// Returns an error if the value at key is of the wrong type. /// /// - pub async fn incr_by(&self, key: K, val: i64) -> Result + pub async fn incr_by(&self, key: K, val: i64) -> Result where + R: RedisResponse, K: Into, { - commands::keys::incr_by(&self.inner, key, val).await + commands::keys::incr_by(&self.inner, key, val).await?.convert() } /// Increment the string representing a floating point number stored at key by `val`. If the key does not exist, it is set to 0 before performing the operation. @@ -1397,11 +1481,12 @@ impl RedisClient { /// Returns an error if key value is the wrong type or if the current value cannot be parsed as a floating point value. /// /// - pub async fn incr_by_float(&self, key: K, val: f64) -> Result + pub async fn incr_by_float(&self, key: K, val: f64) -> Result where + R: RedisResponse, K: Into, { - commands::keys::incr_by_float(&self.inner, key, val).await + commands::keys::incr_by_float(&self.inner, key, val).await?.convert() } /// Decrements the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the operation. @@ -1409,11 +1494,12 @@ impl RedisClient { /// Returns an error if the key contains a value of the wrong type. /// /// - pub async fn decr(&self, key: K) -> Result + pub async fn decr(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::decr(&self.inner, key).await + commands::keys::decr(&self.inner, key).await?.convert() } /// Decrements the number stored at `key` by `val`. If the key does not exist, it is set to 0 before performing the operation. @@ -1421,31 +1507,34 @@ impl RedisClient { /// Returns an error if the key contains a value of the wrong type. /// /// - pub async fn decr_by(&self, key: K, val: i64) -> Result + pub async fn decr_by(&self, key: K, val: i64) -> Result where + R: RedisResponse, K: Into, { - commands::keys::decr_by(&self.inner, key, val).await + commands::keys::decr_by(&self.inner, key, val).await?.convert() } /// Returns the remaining time to live of a key that has a timeout, in seconds. /// /// - pub async fn ttl(&self, key: K) -> Result + pub async fn ttl(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::ttl(&self.inner, key).await + commands::keys::ttl(&self.inner, key).await?.convert() } /// Returns the remaining time to live of a key that has a timeout, in milliseconds. /// /// - pub async fn pttl(&self, key: K) -> Result + pub async fn pttl(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::pttl(&self.inner, key).await + commands::keys::pttl(&self.inner, key).await?.convert() } /// Remove the existing timeout on a key, turning the key from volatile (a key with an expiration) @@ -1454,11 +1543,12 @@ impl RedisClient { /// Returns a boolean value describing whether or not the timeout was removed. /// /// - pub async fn persist(&self, key: K) -> Result + pub async fn persist(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::persist(&self.inner, key).await + commands::keys::persist(&self.inner, key).await?.convert() } /// Set a timeout on key. After the timeout has expired, the key will be automatically deleted. @@ -1466,11 +1556,12 @@ impl RedisClient { /// Returns a boolean value describing whether or not the timeout was added. /// /// - pub async fn expire(&self, key: K, seconds: i64) -> Result + pub async fn expire(&self, key: K, seconds: i64) -> Result where + R: RedisResponse, K: Into, { - commands::keys::expire(&self.inner, key, seconds).await + commands::keys::expire(&self.inner, key, seconds).await?.convert() } /// Set a timeout on a key based on a UNIX timestamp. @@ -1478,21 +1569,23 @@ impl RedisClient { /// Returns a boolean value describing whether or not the timeout was added. /// /// - pub async fn expire_at(&self, key: K, timestamp: i64) -> Result + pub async fn expire_at(&self, key: K, timestamp: i64) -> Result where + R: RedisResponse, K: Into, { - commands::keys::expire_at(&self.inner, key, timestamp).await + commands::keys::expire_at(&self.inner, key, timestamp).await?.convert() } /// Returns number of keys that exist from the `keys` arguments. /// /// - pub async fn exists(&self, keys: K) -> Result + pub async fn exists(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::keys::exists(&self.inner, keys).await + commands::keys::exists(&self.inner, keys).await?.convert() } // ----------- HASHES ------------------ @@ -1500,132 +1593,150 @@ impl RedisClient { /// Removes the specified fields from the hash stored at `key`. /// /// - pub async fn hdel(&self, key: K, fields: F) -> Result + pub async fn hdel(&self, key: K, fields: F) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hdel(&self.inner, key, fields).await + commands::hashes::hdel(&self.inner, key, fields).await?.convert() } /// Returns if `field` is an existing field in the hash stored at `key`. /// /// - pub async fn hexists(&self, key: K, field: F) -> Result + pub async fn hexists(&self, key: K, field: F) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hexists(&self.inner, key, field).await + commands::hashes::hexists(&self.inner, key, field).await?.convert() } /// Returns the value associated with `field` in the hash stored at `key`. /// /// - pub async fn hget(&self, key: K, field: F) -> Result + pub async fn hget(&self, key: K, field: F) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hget(&self.inner, key, field).await + commands::hashes::hget(&self.inner, key, field).await?.convert() } /// Returns all fields and values of the hash stored at `key`. /// /// - pub async fn hgetall(&self, key: K) -> Result + pub async fn hgetall(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::hashes::hgetall(&self.inner, key).await + commands::hashes::hgetall(&self.inner, key).await?.convert() } /// Increments the number stored at `field` in the hash stored at `key` by `increment`. /// /// - pub async fn hincrby(&self, key: K, field: F, increment: i64) -> Result + pub async fn hincrby(&self, key: K, field: F, increment: i64) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hincrby(&self.inner, key, field, increment).await + commands::hashes::hincrby(&self.inner, key, field, increment) + .await? + .convert() } /// Increment the specified `field` of a hash stored at `key`, and representing a floating point number, by the specified `increment`. /// /// - pub async fn hincrbyfloat(&self, key: K, field: F, increment: f64) -> Result + pub async fn hincrbyfloat(&self, key: K, field: F, increment: f64) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hincrbyfloat(&self.inner, key, field, increment).await + commands::hashes::hincrbyfloat(&self.inner, key, field, increment) + .await? + .convert() } /// Returns all field names in the hash stored at `key`. /// /// - pub async fn hkeys(&self, key: K) -> Result + pub async fn hkeys(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::hashes::hkeys(&self.inner, key).await + commands::hashes::hkeys(&self.inner, key).await?.convert() } /// Returns the number of fields contained in the hash stored at `key`. /// /// - pub async fn hlen(&self, key: K) -> Result + pub async fn hlen(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::hashes::hlen(&self.inner, key).await + commands::hashes::hlen(&self.inner, key).await?.convert() } /// Returns the values associated with the specified `fields` in the hash stored at `key`. /// /// - pub async fn hmget(&self, key: K, fields: F) -> Result + pub async fn hmget(&self, key: K, fields: F) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hmget(&self.inner, key, fields).await + commands::hashes::hmget(&self.inner, key, fields).await?.convert() } /// Sets the specified fields to their respective values in the hash stored at `key`. /// /// - pub async fn hmset(&self, key: K, values: V) -> Result + pub async fn hmset(&self, key: K, values: V) -> Result where + R: RedisResponse, K: Into, V: Into, { - commands::hashes::hmset(&self.inner, key, values).await + commands::hashes::hmset(&self.inner, key, values).await?.convert() } /// Sets fields in the hash stored at `key` to their provided values. /// /// - pub async fn hset(&self, key: K, values: V) -> Result + pub async fn hset(&self, key: K, values: V) -> Result where + R: RedisResponse, K: Into, V: Into, { - commands::hashes::hset(&self.inner, key, values).await + commands::hashes::hset(&self.inner, key, values).await?.convert() } /// Sets `field` in the hash stored at `key` to `value`, only if `field` does not yet exist. /// /// - pub async fn hsetnx(&self, key: K, field: F, value: V) -> Result + pub async fn hsetnx(&self, key: K, field: F, value: V) -> Result where + R: RedisResponse, K: Into, F: Into, V: TryInto, V::Error: Into, { - commands::hashes::hsetnx(&self.inner, key, field, to!(value)?).await + commands::hashes::hsetnx(&self.inner, key, field, to!(value)?) + .await? + .convert() } /// When called with just the `key` argument, return a random field from the hash value stored at `key`. @@ -1633,32 +1744,35 @@ impl RedisClient { /// If the provided `count` argument is positive, return an array of distinct fields. /// /// - pub async fn hrandfield(&self, key: K, count: Option<(i64, bool)>) -> Result + pub async fn hrandfield(&self, key: K, count: Option<(i64, bool)>) -> Result where + R: RedisResponse, K: Into, { - commands::hashes::hrandfield(&self.inner, key, count).await + commands::hashes::hrandfield(&self.inner, key, count).await?.convert() } /// Returns the string length of the value associated with `field` in the hash stored at `key`. /// /// - pub async fn hstrlen(&self, key: K, field: F) -> Result + pub async fn hstrlen(&self, key: K, field: F) -> Result where + R: RedisResponse, K: Into, F: Into, { - commands::hashes::hstrlen(&self.inner, key, field).await + commands::hashes::hstrlen(&self.inner, key, field).await?.convert() } /// Returns all values in the hash stored at `key`. /// /// - pub async fn hvals(&self, key: K) -> Result + pub async fn hvals(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::hashes::hvals(&self.inner, key).await + commands::hashes::hvals(&self.inner, key).await?.convert() } // ------------- SETS -------------------- @@ -1666,122 +1780,139 @@ impl RedisClient { /// Add the specified members to the set stored at `key`. /// /// - pub async fn sadd(&self, key: K, members: V) -> Result + pub async fn sadd(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sets::sadd(&self.inner, key, to!(members)?).await + commands::sets::sadd(&self.inner, key, to!(members)?).await?.convert() } /// Returns the set cardinality (number of elements) of the set stored at `key`. /// /// - pub async fn scard(&self, key: K) -> Result + pub async fn scard(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::sets::scard(&self.inner, key).await + commands::sets::scard(&self.inner, key).await?.convert() } /// Returns the members of the set resulting from the difference between the first set and all the successive sets. /// /// - pub async fn sdiff(&self, keys: K) -> Result + pub async fn sdiff(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::sets::sdiff(&self.inner, keys).await + commands::sets::sdiff(&self.inner, keys).await?.convert() } /// This command is equal to SDIFF, but instead of returning the resulting set, it is stored in `destination`. /// /// - pub async fn sdiffstore(&self, dest: D, keys: K) -> Result + pub async fn sdiffstore(&self, dest: D, keys: K) -> Result where + R: RedisResponse, D: Into, K: Into, { - commands::sets::sdiffstore(&self.inner, dest, keys).await + commands::sets::sdiffstore(&self.inner, dest, keys).await?.convert() } /// Returns the members of the set resulting from the intersection of all the given sets. /// /// - pub async fn sinter(&self, keys: K) -> Result + pub async fn sinter(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::sets::sinter(&self.inner, keys).await + commands::sets::sinter(&self.inner, keys).await?.convert() } /// This command is equal to SINTER, but instead of returning the resulting set, it is stored in `destination`. /// /// - pub async fn sinterstore(&self, dest: D, keys: K) -> Result + pub async fn sinterstore(&self, dest: D, keys: K) -> Result where + R: RedisResponse, D: Into, K: Into, { - commands::sets::sinterstore(&self.inner, dest, keys).await + commands::sets::sinterstore(&self.inner, dest, keys).await?.convert() } /// Returns if `member` is a member of the set stored at `key`. /// /// - pub async fn sismember(&self, key: K, member: V) -> Result + pub async fn sismember(&self, key: K, member: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sets::sismember(&self.inner, key, to!(member)?).await + commands::sets::sismember(&self.inner, key, to!(member)?) + .await? + .convert() } /// Returns whether each member is a member of the set stored at `key`. /// /// - pub async fn smismember(&self, key: K, members: V) -> Result + pub async fn smismember(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sets::smismember(&self.inner, key, to!(members)?).await + commands::sets::smismember(&self.inner, key, to!(members)?) + .await? + .convert() } /// Returns all the members of the set value stored at `key`. /// /// - pub async fn smembers(&self, key: K) -> Result + pub async fn smembers(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::sets::smembers(&self.inner, key).await + commands::sets::smembers(&self.inner, key).await?.convert() } /// Move `member` from the set at `source` to the set at `destination`. /// /// - pub async fn smove(&self, source: S, dest: D, member: V) -> Result + pub async fn smove(&self, source: S, dest: D, member: V) -> Result where + R: RedisResponse, S: Into, D: Into, V: TryInto, V::Error: Into, { - commands::sets::smove(&self.inner, source, dest, to!(member)?).await + commands::sets::smove(&self.inner, source, dest, to!(member)?) + .await? + .convert() } /// Removes and returns one or more random members from the set value store at `key`. /// /// - pub async fn spop(&self, key: K, count: Option) -> Result + pub async fn spop(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::sets::spop(&self.inner, key, count).await + commands::sets::spop(&self.inner, key, count).await?.convert() } /// When called with just the key argument, return a random element from the set value stored at `key`. @@ -1789,44 +1920,48 @@ impl RedisClient { /// If the provided `count` argument is positive, return an array of distinct elements. The array's length is either count or the set's cardinality (SCARD), whichever is lower. /// /// - pub async fn srandmember(&self, key: K, count: Option) -> Result + pub async fn srandmember(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::sets::srandmember(&self.inner, key, count).await + commands::sets::srandmember(&self.inner, key, count).await?.convert() } /// Remove the specified members from the set stored at `key`. /// /// - pub async fn srem(&self, key: K, members: V) -> Result + pub async fn srem(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sets::srem(&self.inner, key, to!(members)?).await + commands::sets::srem(&self.inner, key, to!(members)?).await?.convert() } /// Returns the members of the set resulting from the union of all the given sets. /// /// - pub async fn sunion(&self, keys: K) -> Result + pub async fn sunion(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::sets::sunion(&self.inner, keys).await + commands::sets::sunion(&self.inner, keys).await?.convert() } /// This command is equal to SUNION, but instead of returning the resulting set, it is stored in `destination`. /// /// - pub async fn sunionstore(&self, dest: D, keys: K) -> Result + pub async fn sunionstore(&self, dest: D, keys: K) -> Result where + R: RedisResponse, D: Into, K: Into, { - commands::sets::sunionstore(&self.inner, dest, keys).await + commands::sets::sunionstore(&self.inner, dest, keys).await?.convert() } // ------------- SORTED SETS --------------- @@ -1856,7 +1991,7 @@ impl RedisClient { /// Adds all the specified members with the specified scores to the sorted set stored at `key`. /// /// - pub async fn zadd( + pub async fn zadd( &self, key: K, options: Option, @@ -1864,152 +1999,182 @@ impl RedisClient { changed: bool, incr: bool, values: V, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zadd(&self.inner, key, options, ordering, changed, incr, to!(values)?).await + commands::sorted_sets::zadd(&self.inner, key, options, ordering, changed, incr, to!(values)?) + .await? + .convert() } /// Returns the sorted set cardinality (number of elements) of the sorted set stored at `key`. /// /// - pub async fn zcard(&self, key: K) -> Result + pub async fn zcard(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zcard(&self.inner, key).await + commands::sorted_sets::zcard(&self.inner, key).await?.convert() } /// Returns the number of elements in the sorted set at `key` with a score between `min` and `max`. /// /// - pub async fn zcount(&self, key: K, min: f64, max: f64) -> Result + pub async fn zcount(&self, key: K, min: f64, max: f64) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zcount(&self.inner, key, min, max).await + commands::sorted_sets::zcount(&self.inner, key, min, max) + .await? + .convert() } /// This command is similar to ZDIFFSTORE, but instead of storing the resulting sorted set, it is returned to the client. /// /// - pub async fn zdiff(&self, keys: K, withscores: bool) -> Result + pub async fn zdiff(&self, keys: K, withscores: bool) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zdiff(&self.inner, keys, withscores).await + commands::sorted_sets::zdiff(&self.inner, keys, withscores) + .await? + .convert() } /// Computes the difference between the first and all successive input sorted sets and stores the result in `destination`. /// /// - pub async fn zdiffstore(&self, dest: D, keys: K) -> Result + pub async fn zdiffstore(&self, dest: D, keys: K) -> Result where + R: RedisResponse, D: Into, K: Into, { - commands::sorted_sets::zdiffstore(&self.inner, dest, keys).await + commands::sorted_sets::zdiffstore(&self.inner, dest, keys) + .await? + .convert() } /// Increments the score of `member` in the sorted set stored at `key` by `increment`. /// /// - pub async fn zincrby(&self, key: K, increment: f64, member: V) -> Result + pub async fn zincrby(&self, key: K, increment: f64, member: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zincrby(&self.inner, key, increment, to!(member)?).await + commands::sorted_sets::zincrby(&self.inner, key, increment, to!(member)?) + .await? + .convert() } /// This command is similar to ZINTERSTORE, but instead of storing the resulting sorted set, it is returned to the client. /// /// - pub async fn zinter( + pub async fn zinter( &self, keys: K, weights: W, aggregate: Option, withscores: bool, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, W: Into, { - commands::sorted_sets::zinter(&self.inner, keys, weights, aggregate, withscores).await + commands::sorted_sets::zinter(&self.inner, keys, weights, aggregate, withscores) + .await? + .convert() } /// Computes the intersection of the sorted sets given by the specified keys, and stores the result in `destination`. /// /// - pub async fn zinterstore( + pub async fn zinterstore( &self, dest: D, keys: K, weights: W, aggregate: Option, - ) -> Result + ) -> Result where + R: RedisResponse, D: Into, K: Into, W: Into, { - commands::sorted_sets::zinterstore(&self.inner, dest, keys, weights, aggregate).await + commands::sorted_sets::zinterstore(&self.inner, dest, keys, weights, aggregate) + .await? + .convert() } /// When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, /// this command returns the number of elements in the sorted set at key with a value between min and max. /// /// - pub async fn zlexcount(&self, key: K, min: M, max: N) -> Result + pub async fn zlexcount(&self, key: K, min: M, max: N) -> Result where + R: RedisResponse, K: Into, M: TryInto, M::Error: Into, N: TryInto, N::Error: Into, { - commands::sorted_sets::zlexcount(&self.inner, key, to!(min)?, to!(max)?).await + commands::sorted_sets::zlexcount(&self.inner, key, to!(min)?, to!(max)?) + .await? + .convert() } /// Removes and returns up to count members with the highest scores in the sorted set stored at `key`. /// /// - pub async fn zpopmax(&self, key: K, count: Option) -> Result + pub async fn zpopmax(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zpopmax(&self.inner, key, count).await + commands::sorted_sets::zpopmax(&self.inner, key, count).await?.convert() } /// Removes and returns up to count members with the lowest scores in the sorted set stored at `key`. /// /// - pub async fn zpopmin(&self, key: K, count: Option) -> Result + pub async fn zpopmin(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zpopmin(&self.inner, key, count).await + commands::sorted_sets::zpopmin(&self.inner, key, count).await?.convert() } /// When called with just the key argument, return a random element from the sorted set value stored at `key`. /// /// - pub async fn zrandmember(&self, key: K, count: Option<(i64, bool)>) -> Result + pub async fn zrandmember(&self, key: K, count: Option<(i64, bool)>) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zrandmember(&self.inner, key, count).await + commands::sorted_sets::zrandmember(&self.inner, key, count) + .await? + .convert() } /// This command is like ZRANGE, but stores the result in the `destination` key. /// /// - pub async fn zrangestore( + pub async fn zrangestore( &self, dest: D, source: S, @@ -2018,8 +2183,9 @@ impl RedisClient { sort: Option, rev: bool, limit: Option, - ) -> Result + ) -> Result where + R: RedisResponse, D: Into, S: Into, M: TryInto, @@ -2027,7 +2193,9 @@ impl RedisClient { N: TryInto, N::Error: Into, { - commands::sorted_sets::zrangestore(&self.inner, dest, source, to!(min)?, to!(max)?, sort, rev, limit).await + commands::sorted_sets::zrangestore(&self.inner, dest, source, to!(min)?, to!(max)?, sort, rev, limit) + .await? + .convert() } /// Returns the specified range of elements in the sorted set stored at `key`. @@ -2142,25 +2310,31 @@ impl RedisClient { /// Returns the rank of member in the sorted set stored at `key`, with the scores ordered from low to high. /// /// - pub async fn zrank(&self, key: K, member: V) -> Result + pub async fn zrank(&self, key: K, member: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zrank(&self.inner, key, to!(member)?).await + commands::sorted_sets::zrank(&self.inner, key, to!(member)?) + .await? + .convert() } /// Removes the specified members from the sorted set stored at `key`. Non existing members are ignored. /// /// - pub async fn zrem(&self, key: K, members: V) -> Result + pub async fn zrem(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zrem(&self.inner, key, to!(members)?).await + commands::sorted_sets::zrem(&self.inner, key, to!(members)?) + .await? + .convert() } /// When all the elements in a sorted set are inserted with the same score, in order to force lexicographical @@ -2168,73 +2342,91 @@ impl RedisClient { /// specified by `min` and `max`. /// /// - pub async fn zremrangebylex(&self, key: K, min: M, max: N) -> Result + pub async fn zremrangebylex(&self, key: K, min: M, max: N) -> Result where + R: RedisResponse, K: Into, M: TryInto, M::Error: Into, N: TryInto, N::Error: Into, { - commands::sorted_sets::zremrangebylex(&self.inner, key, to!(min)?, to!(max)?).await + commands::sorted_sets::zremrangebylex(&self.inner, key, to!(min)?, to!(max)?) + .await? + .convert() } /// Removes all elements in the sorted set stored at `key` with rank between `start` and `stop`. /// /// - pub async fn zremrangebyrank(&self, key: K, start: i64, stop: i64) -> Result + pub async fn zremrangebyrank(&self, key: K, start: i64, stop: i64) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zremrangebyrank(&self.inner, key, start, stop).await + commands::sorted_sets::zremrangebyrank(&self.inner, key, start, stop) + .await? + .convert() } /// Removes all elements in the sorted set stored at `key` with a score between `min` and `max`. /// /// - pub async fn zremrangebyscore(&self, key: K, min: M, max: N) -> Result + pub async fn zremrangebyscore(&self, key: K, min: M, max: N) -> Result where + R: RedisResponse, K: Into, M: TryInto, M::Error: Into, N: TryInto, N::Error: Into, { - commands::sorted_sets::zremrangebyscore(&self.inner, key, to!(min)?, to!(max)?).await + commands::sorted_sets::zremrangebyscore(&self.inner, key, to!(min)?, to!(max)?) + .await? + .convert() } /// Returns the specified range of elements in the sorted set stored at `key`. /// /// - pub async fn zrevrange(&self, key: K, start: i64, stop: i64, withscores: bool) -> Result + pub async fn zrevrange(&self, key: K, start: i64, stop: i64, withscores: bool) -> Result where + R: RedisResponse, K: Into, { - commands::sorted_sets::zrevrange(&self.inner, key, start, stop, withscores).await + commands::sorted_sets::zrevrange(&self.inner, key, start, stop, withscores) + .await? + .convert() } /// Returns the rank of `member` in the sorted set stored at `key`, with the scores ordered from high to low. /// /// - pub async fn zrevrank(&self, key: K, member: V) -> Result + pub async fn zrevrank(&self, key: K, member: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zrevrank(&self.inner, key, to!(member)?).await + commands::sorted_sets::zrevrank(&self.inner, key, to!(member)?) + .await? + .convert() } /// Returns the score of `member` in the sorted set at `key`. /// /// - pub async fn zscore(&self, key: K, member: V) -> Result + pub async fn zscore(&self, key: K, member: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zscore(&self.inner, key, to!(member)?).await + commands::sorted_sets::zscore(&self.inner, key, to!(member)?) + .await? + .convert() } /// This command is similar to ZUNIONSTORE, but instead of storing the resulting sorted set, it is returned to the client. @@ -2257,31 +2449,37 @@ impl RedisClient { /// Computes the union of the sorted sets given by the specified keys, and stores the result in `destination`. /// /// - pub async fn zunionstore( + pub async fn zunionstore( &self, dest: D, keys: K, weights: W, aggregate: Option, - ) -> Result + ) -> Result where + R: RedisResponse, D: Into, K: Into, W: Into, { - commands::sorted_sets::zunionstore(&self.inner, dest, keys, weights, aggregate).await + commands::sorted_sets::zunionstore(&self.inner, dest, keys, weights, aggregate) + .await? + .convert() } /// Returns the scores associated with the specified members in the sorted set stored at `key`. /// /// - pub async fn zmscore(&self, key: K, members: V) -> Result + pub async fn zmscore(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::sorted_sets::zmscore(&self.inner, key, to!(members)?).await + commands::sorted_sets::zmscore(&self.inner, key, to!(members)?) + .await? + .convert() } // ------------- LISTS ------------------ @@ -2290,50 +2488,56 @@ impl RedisClient { /// any of the given lists. An element is popped from the head of the first list that is non-empty, with the given keys being checked in the order that they are given. /// /// - pub async fn blpop(&self, keys: K, timeout: f64) -> Result + pub async fn blpop(&self, keys: K, timeout: f64) -> Result where + R: RedisResponse, K: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::lists::blpop(&self.inner, keys, timeout).await + commands::lists::blpop(&self.inner, keys, timeout).await?.convert() } /// BRPOP is a blocking list pop primitive. It is the blocking version of RPOP because it blocks the connection when there are no elements to pop from any of the /// given lists. An element is popped from the tail of the first list that is non-empty, with the given keys being checked in the order that they are given. /// /// - pub async fn brpop(&self, keys: K, timeout: f64) -> Result + pub async fn brpop(&self, keys: K, timeout: f64) -> Result where + R: RedisResponse, K: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::lists::brpop(&self.inner, keys, timeout).await + commands::lists::brpop(&self.inner, keys, timeout).await?.convert() } /// The blocking equivalent of [Self::rpoplpush]. /// /// - pub async fn brpoplpush(&self, source: S, destination: D, timeout: f64) -> Result + pub async fn brpoplpush(&self, source: S, destination: D, timeout: f64) -> Result where + R: RedisResponse, S: Into, D: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::lists::brpoplpush(&self.inner, source, destination, timeout).await + commands::lists::brpoplpush(&self.inner, source, destination, timeout) + .await? + .convert() } /// The blocking equivalent of [Self::lmove]. /// /// - pub async fn blmove( + pub async fn blmove( &self, source: S, destination: D, source_direction: LMoveDirection, destination_direction: LMoveDirection, timeout: f64, - ) -> Result + ) -> Result where + R: RedisResponse, S: Into, D: Into, { @@ -2347,207 +2551,242 @@ impl RedisClient { destination_direction, timeout, ) - .await + .await? + .convert() } /// Returns the element at index index in the list stored at key. /// /// - pub async fn lindex(&self, key: K, index: i64) -> Result + pub async fn lindex(&self, key: K, index: i64) -> Result where + R: RedisResponse, K: Into, { - commands::lists::lindex(&self.inner, key, index).await + commands::lists::lindex(&self.inner, key, index).await?.convert() } /// Inserts element in the list stored at key either before or after the reference value `pivot`. /// /// - pub async fn linsert( + pub async fn linsert( &self, key: K, location: ListLocation, pivot: P, element: V, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, P: TryInto, P::Error: Into, V: TryInto, V::Error: Into, { - commands::lists::linsert(&self.inner, key, location, to!(pivot)?, to!(element)?).await + commands::lists::linsert(&self.inner, key, location, to!(pivot)?, to!(element)?) + .await? + .convert() } /// Returns the length of the list stored at key. /// /// - pub async fn llen(&self, key: K) -> Result + pub async fn llen(&self, key: K) -> Result where + R: RedisResponse, K: Into, { - commands::lists::llen(&self.inner, key).await + commands::lists::llen(&self.inner, key).await?.convert() } /// Removes and returns the first elements of the list stored at key. /// /// - pub async fn lpop(&self, key: K, count: Option) -> Result + pub async fn lpop(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::lists::lpop(&self.inner, key, count).await + commands::lists::lpop(&self.inner, key, count).await?.convert() } /// The command returns the index of matching elements inside a Redis list. /// /// - pub async fn lpos( + pub async fn lpos( &self, key: K, element: V, rank: Option, count: Option, maxlen: Option, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::lpos(&self.inner, key, to!(element)?, rank, count, maxlen).await + commands::lists::lpos(&self.inner, key, to!(element)?, rank, count, maxlen) + .await? + .convert() } /// Insert all the specified values at the head of the list stored at `key`. /// /// - pub async fn lpush(&self, key: K, elements: V) -> Result + pub async fn lpush(&self, key: K, elements: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::lpush(&self.inner, key, to!(elements)?).await + commands::lists::lpush(&self.inner, key, to!(elements)?) + .await? + .convert() } /// Inserts specified values at the head of the list stored at `key`, only if `key` already exists and holds a list. /// /// - pub async fn lpushx(&self, key: K, elements: V) -> Result + pub async fn lpushx(&self, key: K, elements: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::lpushx(&self.inner, key, to!(elements)?).await + commands::lists::lpushx(&self.inner, key, to!(elements)?) + .await? + .convert() } /// Returns the specified elements of the list stored at `key`. /// /// - pub async fn lrange(&self, key: K, start: i64, stop: i64) -> Result + pub async fn lrange(&self, key: K, start: i64, stop: i64) -> Result where + R: RedisResponse, K: Into, { - commands::lists::lrange(&self.inner, key, start, stop).await + commands::lists::lrange(&self.inner, key, start, stop).await?.convert() } /// Removes the first `count` occurrences of elements equal to `element` from the list stored at `key`. /// /// - pub async fn lrem(&self, key: K, count: i64, element: V) -> Result + pub async fn lrem(&self, key: K, count: i64, element: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::lrem(&self.inner, key, count, to!(element)?).await + commands::lists::lrem(&self.inner, key, count, to!(element)?) + .await? + .convert() } /// Sets the list element at `index` to `element`. /// /// - pub async fn lset(&self, key: K, index: i64, element: V) -> Result + pub async fn lset(&self, key: K, index: i64, element: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::lset(&self.inner, key, index, to!(element)?).await + commands::lists::lset(&self.inner, key, index, to!(element)?) + .await? + .convert() } /// Trim an existing list so that it will contain only the specified range of elements specified. /// /// - pub async fn ltrim(&self, key: K, start: i64, stop: i64) -> Result + pub async fn ltrim(&self, key: K, start: i64, stop: i64) -> Result where + R: RedisResponse, K: Into, { - commands::lists::ltrim(&self.inner, key, start, stop).await + commands::lists::ltrim(&self.inner, key, start, stop).await?.convert() } /// Removes and returns the last elements of the list stored at `key`. /// /// - pub async fn rpop(&self, key: K, count: Option) -> Result + pub async fn rpop(&self, key: K, count: Option) -> Result where + R: RedisResponse, K: Into, { - commands::lists::rpop(&self.inner, key, count).await + commands::lists::rpop(&self.inner, key, count).await?.convert() } /// Atomically returns and removes the last element (tail) of the list stored at `source`, and pushes the element at the first element (head) of the list stored at `destination`. /// /// - pub async fn rpoplpush(&self, source: S, dest: D) -> Result + pub async fn rpoplpush(&self, source: S, dest: D) -> Result where + R: RedisResponse, S: Into, D: Into, { - commands::lists::rpoplpush(&self.inner, source, dest).await + commands::lists::rpoplpush(&self.inner, source, dest).await?.convert() } /// Atomically returns and removes the first/last element (head/tail depending on the source direction argument) of the list stored at `source`, and pushes /// the element at the first/last element (head/tail depending on the destination direction argument) of the list stored at `destination`. /// /// - pub async fn lmove( + pub async fn lmove( &self, source: S, dest: D, source_direction: LMoveDirection, dest_direction: LMoveDirection, - ) -> Result + ) -> Result where + R: RedisResponse, S: Into, D: Into, { - commands::lists::lmove(&self.inner, source, dest, source_direction, dest_direction).await + commands::lists::lmove(&self.inner, source, dest, source_direction, dest_direction) + .await? + .convert() } /// Insert all the specified values at the tail of the list stored at `key`. /// /// - pub async fn rpush(&self, key: K, elements: V) -> Result + pub async fn rpush(&self, key: K, elements: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::rpush(&self.inner, key, to!(elements)?).await + commands::lists::rpush(&self.inner, key, to!(elements)?) + .await? + .convert() } /// Inserts specified values at the tail of the list stored at `key`, only if key already exists and holds a list. /// /// - pub async fn rpushx(&self, key: K, elements: V) -> Result + pub async fn rpushx(&self, key: K, elements: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::lists::rpushx(&self.inner, key, to!(elements)?).await + commands::lists::rpushx(&self.inner, key, to!(elements)?) + .await? + .convert() } // ------------- GEO -------------------- @@ -2555,34 +2794,40 @@ impl RedisClient { /// Adds the specified geospatial items (longitude, latitude, name) to the specified key. /// /// - pub async fn geoadd( + pub async fn geoadd( &self, key: K, options: Option, changed: bool, values: V, - ) -> Result + ) -> Result where + R: RedisResponse, K: Into, V: Into, { - commands::geo::geoadd(&self.inner, key, options, changed, values).await + commands::geo::geoadd(&self.inner, key, options, changed, values) + .await? + .convert() } /// Return valid Geohash strings representing the position of one or more elements in a sorted set value representing a geospatial index (where elements were added using GEOADD). /// /// - pub async fn geohash(&self, key: K, members: V) -> Result + pub async fn geohash(&self, key: K, members: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::geo::geohash(&self.inner, key, to!(members)?).await + commands::geo::geohash(&self.inner, key, to!(members)?).await?.convert() } /// Return the positions (longitude,latitude) of all the specified members of the geospatial index represented by the sorted set at key. /// + /// Callers can use [as_geo_position](crate::types::RedisValue::as_geo_position) to lazily parse results as needed. + /// /// pub async fn geopos(&self, key: K, members: V) -> Result where @@ -2596,21 +2841,18 @@ impl RedisClient { /// Return the distance between two members in the geospatial index represented by the sorted set. /// /// - pub async fn geodist( - &self, - key: K, - src: S, - dest: D, - unit: Option, - ) -> Result + pub async fn geodist(&self, key: K, src: S, dest: D, unit: Option) -> Result where + R: RedisResponse, K: Into, S: TryInto, S::Error: Into, D: TryInto, D::Error: Into, { - commands::geo::geodist(&self.inner, key, to!(src)?, to!(dest)?, unit).await + commands::geo::geodist(&self.inner, key, to!(src)?, to!(dest)?, unit) + .await? + .convert() } /// Return the members of a sorted set populated with geospatial information using GEOADD, which are within the borders of the area specified with @@ -2730,7 +2972,7 @@ impl RedisClient { /// This command is like GEOSEARCH, but stores the result in destination key. Returns the number of members added to the destination key. /// /// - pub async fn geosearchstore( + pub async fn geosearchstore( &self, dest: D, source: S, @@ -2741,8 +2983,9 @@ impl RedisClient { ord: Option, count: Option<(u64, Any)>, storedist: bool, - ) -> Result + ) -> Result where + R: RedisResponse, D: Into, S: Into, { @@ -2758,7 +3001,8 @@ impl RedisClient { count, storedist, ) - .await + .await? + .convert() } // ------------ HYPERLOGLOG -------------- @@ -2766,13 +3010,16 @@ impl RedisClient { /// Adds all the element arguments to the HyperLogLog data structure stored at the variable name specified as first argument. /// /// - pub async fn pfadd(&self, key: K, elements: V) -> Result + pub async fn pfadd(&self, key: K, elements: V) -> Result where + R: RedisResponse, K: Into, V: TryInto, V::Error: Into, { - commands::hyperloglog::pfadd(&self.inner, key, to!(elements)?).await + commands::hyperloglog::pfadd(&self.inner, key, to!(elements)?) + .await? + .convert() } /// When called with a single key, returns the approximated cardinality computed by the HyperLogLog data structure stored at @@ -2782,23 +3029,27 @@ impl RedisClient { /// internally merging the HyperLogLogs stored at the provided keys into a temporary HyperLogLog. /// /// - pub async fn pfcount(&self, keys: K) -> Result + pub async fn pfcount(&self, keys: K) -> Result where + R: RedisResponse, K: Into, { - commands::hyperloglog::pfcount(&self.inner, keys).await + commands::hyperloglog::pfcount(&self.inner, keys).await?.convert() } /// Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of the observed - /// Sets of the source HyperLogLog structures. + /// sets of the source HyperLogLog structures. /// /// - pub async fn pfmerge(&self, dest: D, sources: S) -> Result + pub async fn pfmerge(&self, dest: D, sources: S) -> Result where + R: RedisResponse, D: Into, S: Into, { - commands::hyperloglog::pfmerge(&self.inner, dest, sources).await + commands::hyperloglog::pfmerge(&self.inner, dest, sources) + .await? + .convert() } // -------------- LUA ------------------ @@ -2806,19 +3057,19 @@ impl RedisClient { /// Load a script into the scripts cache, without executing it. After the specified command is loaded into the script cache it will be callable using EVALSHA with the correct SHA1 digest of the script. /// /// - pub async fn script_load(&self, script: S) -> Result + pub async fn script_load(&self, script: S) -> Result where S: Into, { - commands::lua::script_load(&self.inner, script).await + commands::lua::script_load(&self.inner, script).await?.convert() } /// A clustered variant of [script_load](Self::script_load) that loads the script on all primary nodes in a cluster. - pub async fn script_load_cluster(&self, script: S) -> Result + pub async fn script_load_cluster(&self, script: S) -> Result where S: Into, { - commands::lua::script_load_cluster(&self.inner, script).await + commands::lua::script_load_cluster(&self.inner, script).await?.convert() } /// Kills the currently executing Lua script, assuming no write operation was yet performed by the script. @@ -2871,29 +3122,35 @@ impl RedisClient { /// Evaluates a script cached on the server side by its SHA1 digest. /// /// - pub async fn evalsha(&self, hash: S, keys: K, args: V) -> Result + pub async fn evalsha(&self, hash: S, keys: K, args: V) -> Result where + R: RedisResponse, S: Into, K: Into, V: TryInto, V::Error: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::lua::evalsha(&self.inner, hash, keys, to!(args)?).await + commands::lua::evalsha(&self.inner, hash, keys, to!(args)?) + .await? + .convert() } /// Evaluate a Lua script on the server. /// /// - pub async fn eval(&self, script: S, keys: K, args: V) -> Result + pub async fn eval(&self, script: S, keys: K, args: V) -> Result where + R: RedisResponse, S: Into, K: Into, V: TryInto, V::Error: Into, { utils::disallow_during_transaction(&self.inner)?; - commands::lua::eval(&self.inner, script, keys, to!(args)?).await + commands::lua::eval(&self.inner, script, keys, to!(args)?) + .await? + .convert() } // --------------- SCANNING --------------- diff --git a/src/error.rs b/src/error.rs index 532ce909..ae119e24 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,6 +5,7 @@ use redis_protocol::types::RedisProtocolError; use semver::Error as SemverError; use std::borrow::{Borrow, Cow}; use std::convert::Infallible; +use std::error::Error; use std::fmt; use std::fmt::Display; use std::io::Error as IoError; @@ -14,7 +15,6 @@ use std::str::Utf8Error; use std::string::FromUtf8Error; use tokio::task::JoinError; use url::ParseError; -use std::error::Error; /// An enum representing the type of error from Redis. #[derive(Debug, Clone, Eq, PartialEq)] @@ -43,6 +43,8 @@ pub enum RedisErrorKind { Timeout, /// An error used to indicate that the cluster's state has changed. These errors will show up on the `on_error` error stream even though the client will automatically attempt to recover. Cluster, + /// A parser error. + Parse, } impl RedisErrorKind { @@ -60,6 +62,7 @@ impl RedisErrorKind { RedisErrorKind::Timeout => "Timeout Error", RedisErrorKind::Tls => "TLS Error", RedisErrorKind::Config => "Config Error", + RedisErrorKind::Parse => "Parse Error", } } } @@ -150,25 +153,25 @@ impl From for RedisError { impl From for RedisError { fn from(_: ParseFloatError) -> Self { - RedisError::new(RedisErrorKind::Unknown, "Invalid floating point number.") + RedisError::new(RedisErrorKind::Parse, "Invalid floating point number.") } } impl From for RedisError { fn from(_: ParseIntError) -> Self { - RedisError::new(RedisErrorKind::Unknown, "Invalid integer string.") + RedisError::new(RedisErrorKind::Parse, "Invalid integer string.") } } impl From for RedisError { fn from(_: FromUtf8Error) -> Self { - RedisError::new(RedisErrorKind::Unknown, "Invalid UTF8 string.") + RedisError::new(RedisErrorKind::Parse, "Invalid UTF8 string.") } } impl From for RedisError { fn from(_: Utf8Error) -> Self { - RedisError::new(RedisErrorKind::Unknown, "Invalid UTF8 string.") + RedisError::new(RedisErrorKind::Parse, "Invalid UTF8 string.") } } @@ -284,6 +287,14 @@ impl RedisError { RedisError::new(RedisErrorKind::Timeout, "") } + /// Create a new parse error with the provided details. + pub(crate) fn new_parse(details: T) -> RedisError + where + T: Into>, + { + RedisError::new(RedisErrorKind::Parse, details) + } + /// Whether or not the error is a Canceled error. pub fn is_canceled(&self) -> bool { match self.kind { @@ -297,4 +308,4 @@ impl Error for RedisError { fn source(&self) -> Option<&(dyn Error + 'static)> { None } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index d20c1b86..447ea658 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,13 +19,21 @@ //! let jh = client.connect(Some(policy)); //! // wait for the client to connect //! let _ = client.wait_for_connect().await?; -//! -//! println!("Foo: {:?}", client.get("foo").await?); -//! let _ = client.set("foo", "bar", None, None, false).await?; -//! println!("Foo: {:?}", client.get("foo".to_owned()).await?); +//! let _ = client.flushall(false).await?; +//! +//! let foo: Option = client.get("foo").await?; +//! println!("Foo: {:?}", foo); +//! assert_eq!(foo, None); +//! +//! let _: () = client.set("foo", "bar", None, None, false).await?; +//! // or use turbofish to declare types. the first type is always the response. +//! println!("Foo: {:?}", client.get::("foo".to_owned()).await?); +//! // or use a lower level interface for responses to defer parsing, etc +//! let foo: RedisValue = client.get("foo").await?; +//! assert!(foo.is_string()); //! //! let _ = client.quit().await?; -//! // wait for the task driving the connection to finish +//! // and/or wait for the task driving the connection to finish //! let _ = jh.await; //! Ok(()) //! } @@ -67,6 +75,7 @@ mod commands; mod inner; mod multiplexer; mod protocol; +mod response; mod trace; mod utils; diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 00000000..009c06aa --- /dev/null +++ b/src/response.rs @@ -0,0 +1,499 @@ +use crate::error::RedisError; +use crate::types::{RedisValue, QUEUED}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::hash::{BuildHasher, Hash}; +use std::str::FromStr; + +macro_rules! to_signed_number( + ($t:ty, $v:expr) => { + match $v { + RedisValue::Integer(i) => Ok(i as $t), + RedisValue::String(s) => s.parse::<$t>().map_err(|e| e.into()), + RedisValue::Array(mut a) => if a.len() == 1 { + match a.pop().unwrap() { + RedisValue::Integer(i) => Ok(i as $t), + RedisValue::String(s) => s.parse::<$t>().map_err(|e| e.into()), + _ => Err(RedisError::new_parse("Cannot convert to number.")) + } + }else{ + Err(RedisError::new_parse("Cannot convert to number.")) + } + _ => Err(RedisError::new_parse("Cannot convert to number.")), + } + } +); + +macro_rules! to_unsigned_number( + ($t:ty, $v:expr) => { + match $v { + RedisValue::Integer(i) => if i < 0 { + Err(RedisError::new_parse("Cannot convert from negative number.")) + }else{ + Ok(i as $t) + }, + RedisValue::String(s) => s.parse::<$t>().map_err(|e| e.into()), + RedisValue::Array(mut a) => if a.len() == 1 { + match a.pop().unwrap() { + RedisValue::Integer(i) => if i < 0 { + Err(RedisError::new_parse("Cannot convert from negative number.")) + }else{ + Ok(i as $t) + }, + RedisValue::String(s) => s.parse::<$t>().map_err(|e| e.into()), + _ => Err(RedisError::new_parse("Cannot convert to number.")) + } + }else{ + Err(RedisError::new_parse("Cannot convert to number.")) + } + _ => Err(RedisError::new_parse("Cannot convert to number.")), + } + } +); + +macro_rules! impl_signed_number ( + ($t:ty) => { + impl RedisResponse for $t { + fn from_value(value: RedisValue) -> Result<$t, RedisError> { + to_signed_number!($t, value) + } + } + } +); + +macro_rules! impl_unsigned_number ( + ($t:ty) => { + impl RedisResponse for $t { + fn from_value(value: RedisValue) -> Result<$t, RedisError> { + to_unsigned_number!($t, value) + } + } + } +); + +pub trait RedisResponse: Sized { + fn from_value(value: RedisValue) -> Result; + + #[doc(hidden)] + fn from_values(values: Vec) -> Result, RedisError> { + values.into_iter().map(|v| Self::from_value(v)).collect() + } + + #[doc(hidden)] + // FIXME if/when specialization is stable + fn from_bytes(_: Vec) -> Option> { + None + } +} + +impl RedisResponse for RedisValue { + fn from_value(value: RedisValue) -> Result { + Ok(value) + } +} + +impl RedisResponse for () { + fn from_value(_: RedisValue) -> Result { + Ok(()) + } +} + +impl_signed_number!(i8); +impl_signed_number!(i16); +impl_signed_number!(i32); +impl_signed_number!(i64); +impl_signed_number!(i128); +impl_signed_number!(isize); + +impl RedisResponse for u8 { + fn from_value(value: RedisValue) -> Result { + to_unsigned_number!(u8, value) + } + + fn from_bytes(v: Vec) -> Option> { + Some(v) + } +} + +impl_unsigned_number!(u16); +impl_unsigned_number!(u32); +impl_unsigned_number!(u64); +impl_unsigned_number!(u128); +impl_unsigned_number!(usize); + +impl RedisResponse for String { + fn from_value(value: RedisValue) -> Result { + value + .into_string() + .ok_or(RedisError::new_parse("Could not convert to string.")) + } +} + +impl RedisResponse for f64 { + fn from_value(value: RedisValue) -> Result { + value + .as_f64() + .ok_or(RedisError::new_parse("Could not convert to double.")) + } +} + +impl RedisResponse for f32 { + fn from_value(value: RedisValue) -> Result { + value + .as_f64() + .map(|f| f as f32) + .ok_or(RedisError::new_parse("Could not convert to float.")) + } +} + +impl RedisResponse for bool { + fn from_value(value: RedisValue) -> Result { + value + .as_bool() + .ok_or(RedisError::new_parse("Could not convert to bool.")) + } +} + +impl RedisResponse for Option +where + T: RedisResponse, +{ + fn from_value(value: RedisValue) -> Result, RedisError> { + if value.is_null() { + Ok(None) + } else { + Ok(Some(T::from_value(value)?)) + } + } +} + +impl RedisResponse for Vec +where + T: RedisResponse, +{ + fn from_value(value: RedisValue) -> Result, RedisError> { + match value { + RedisValue::Bytes(bytes) => T::from_bytes(bytes).ok_or(RedisError::new_parse("Cannot convert from bytes")), + RedisValue::String(string) => { + // hacky way to check if T is bytes without consuming `string` + if T::from_bytes(vec![]).is_some() { + T::from_bytes(string.into_bytes()).ok_or(RedisError::new_parse("Could not convert string to bytes.")) + } else { + Ok(vec![T::from_value(RedisValue::String(string))?]) + } + } + RedisValue::Array(values) => T::from_values(values), + RedisValue::Map(map) => { + // not being able to use collect() here is unfortunate + let out = Vec::with_capacity(map.len() * 2); + map.inner().into_iter().fold(Ok(out), |out, (key, value)| { + out.and_then(|mut out| { + out.push(T::from_value(RedisValue::String(key))?); + out.push(T::from_value(value)?); + Ok(out) + }) + }) + } + RedisValue::Null => Ok(vec![]), + RedisValue::Integer(i) => Ok(vec![T::from_value(RedisValue::Integer(i))?]), + RedisValue::Queued => Ok(vec![T::from_value(RedisValue::String(QUEUED.into()))?]), + } + } +} + +impl RedisResponse for HashMap +where + K: FromStr + Eq + Hash, + V: RedisResponse, + S: BuildHasher + Default, +{ + fn from_value(value: RedisValue) -> Result { + let as_map = if value.is_array() || value.is_map() { + value + .into_map() + .map_err(|_| RedisError::new_parse("Cannot convert to map."))? + } else { + return Err(RedisError::new_parse("Cannot convert to map.")); + }; + + as_map + .inner() + .into_iter() + .map(|(k, v)| { + Ok(( + k.parse::() + .map_err(|_| RedisError::new_parse("Cannot convert key."))?, + V::from_value(v)?, + )) + }) + .collect() + } +} + +impl RedisResponse for HashSet +where + V: RedisResponse + Hash + Eq, + S: BuildHasher + Default, +{ + fn from_value(value: RedisValue) -> Result { + value.into_array().into_iter().map(|v| V::from_value(v)).collect() + } +} + +impl RedisResponse for BTreeMap +where + K: FromStr + Ord, + V: RedisResponse, +{ + fn from_value(value: RedisValue) -> Result { + let as_map = if value.is_array() || value.is_map() { + value + .into_map() + .map_err(|_| RedisError::new_parse("Cannot convert to map."))? + } else { + return Err(RedisError::new_parse("Cannot convert to map.")); + }; + + as_map + .inner() + .into_iter() + .map(|(k, v)| { + Ok(( + k.parse::() + .map_err(|_| RedisError::new_parse("Cannot convert key."))?, + V::from_value(v)?, + )) + }) + .collect() + } +} + +impl RedisResponse for BTreeSet +where + V: RedisResponse + Ord, +{ + fn from_value(value: RedisValue) -> Result { + value.into_array().into_iter().map(|v| V::from_value(v)).collect() + } +} + +// adapted from mitsuhiko +// this seems much better than making callers deal with hlists +macro_rules! impl_redis_response_tuple { + () => (); + ($($name:ident,)+) => ( + impl<$($name: RedisResponse),*> RedisResponse for ($($name,)*) { + #[allow(non_snake_case, unused_variables)] + fn from_value(v: RedisValue) -> Result<($($name,)*), RedisError> { + if let RedisValue::Array(mut values) = v { + let mut n = 0; + $(let $name = (); n += 1;)* + if values.len() != n { + return Err(RedisError::new_parse("Invalid tuple dimension.")); + } + + // since we have ownership over the values we have some freedom in how to implement this + values.reverse(); + Ok(($({let $name = (); values + .pop() + .ok_or(RedisError::new_parse("Expected value, found none."))? + .convert()? + },)*)) + }else{ + Err(RedisError::new_parse("Could not convert to tuple.")) + } + } + + #[allow(non_snake_case, unused_variables)] + fn from_values(mut values: Vec) -> Result, RedisError> { + let mut n = 0; + $(let $name = (); n += 1;)* + if values.len() % n != 0 { + return Err(RedisError::new_parse("Invalid tuple dimension.")) + } + + let mut out = Vec::with_capacity(values.len() / n); + // this would be cleaner if there were an owned `chunks` variant + for chunk in values.chunks_exact_mut(n) { + match chunk { + [$($name),*] => out.push(($($name.take().convert()?),*),), + _ => unreachable!(), + } + } + + Ok(out) + } + } + impl_redis_response_peel!($($name,)*); + ) +} + +macro_rules! impl_redis_response_peel { + ($name:ident, $($other:ident,)*) => (impl_redis_response_tuple!($($other,)*);) +} + +impl_redis_response_tuple! { T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, } + +#[cfg(test)] +mod tests { + use crate::types::RedisValue; + use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; + + #[test] + fn should_convert_null() { + let _foo: () = RedisValue::Null.convert().unwrap(); + } + + #[test] + fn should_convert_signed_numeric_types() { + let _foo: i8 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i8 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i16 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i16 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i32 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i32 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i64 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i64 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i128 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: i128 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: isize = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: isize = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: f32 = RedisValue::String("123.5".into()).convert().unwrap(); + assert_eq!(_foo, 123.5); + let _foo: f64 = RedisValue::String("123.5".into()).convert().unwrap(); + assert_eq!(_foo, 123.5); + } + + #[test] + fn should_convert_unsigned_numeric_types() { + let _foo: u8 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u8 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u16 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u16 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u32 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u32 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u64 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u64 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u128 = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: u128 = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: usize = RedisValue::String("123".into()).convert().unwrap(); + assert_eq!(_foo, 123); + let _foo: usize = RedisValue::Integer(123).convert().unwrap(); + assert_eq!(_foo, 123); + } + + #[test] + fn should_convert_strings() { + let _foo: String = RedisValue::String("foo".into()).convert().unwrap(); + assert_eq!(_foo, "foo".to_owned()); + } + + #[test] + fn should_convert_bools() { + let _foo: bool = RedisValue::Integer(0).convert().unwrap(); + assert_eq!(_foo, false); + let _foo: bool = RedisValue::Integer(1).convert().unwrap(); + assert_eq!(_foo, true); + let _foo: bool = RedisValue::String("0".into()).convert().unwrap(); + assert_eq!(_foo, false); + let _foo: bool = RedisValue::String("1".into()).convert().unwrap(); + assert_eq!(_foo, true); + } + + #[test] + fn should_convert_bytes() { + let _foo: Vec = RedisValue::Bytes("foo".as_bytes().to_vec()).convert().unwrap(); + assert_eq!(_foo, "foo".as_bytes().to_vec()); + let _foo: Vec = RedisValue::String("foo".into()).convert().unwrap(); + assert_eq!(_foo, "foo".as_bytes().to_vec()); + let _foo: Vec = RedisValue::Array(vec![102.into(), 111.into(), 111.into()]) + .convert() + .unwrap(); + assert_eq!(_foo, "foo".as_bytes().to_vec()); + } + + #[test] + fn should_convert_arrays() { + let foo: Vec = RedisValue::Array(vec!["a".into(), "b".into()]).convert().unwrap(); + assert_eq!(foo, vec!["a".to_owned(), "b".to_owned()]); + } + + #[test] + fn should_convert_hash_maps() { + let foo: HashMap = RedisValue::Array(vec!["a".into(), 1.into(), "b".into(), 2.into()]) + .convert() + .unwrap(); + + let mut expected = HashMap::new(); + expected.insert("a".to_owned(), 1); + expected.insert("b".to_owned(), 2); + assert_eq!(foo, expected); + } + + #[test] + fn should_convert_hash_sets() { + let foo: HashSet = RedisValue::Array(vec!["a".into(), "b".into()]).convert().unwrap(); + + let mut expected = HashSet::new(); + expected.insert("a".to_owned()); + expected.insert("b".to_owned()); + assert_eq!(foo, expected); + } + + #[test] + fn should_convert_btree_maps() { + let foo: BTreeMap = RedisValue::Array(vec!["a".into(), 1.into(), "b".into(), 2.into()]) + .convert() + .unwrap(); + + let mut expected = BTreeMap::new(); + expected.insert("a".to_owned(), 1); + expected.insert("b".to_owned(), 2); + assert_eq!(foo, expected); + } + + #[test] + fn should_convert_btree_sets() { + let foo: BTreeSet = RedisValue::Array(vec!["a".into(), "b".into()]).convert().unwrap(); + + let mut expected = BTreeSet::new(); + expected.insert("a".to_owned()); + expected.insert("b".to_owned()); + assert_eq!(foo, expected); + } + + #[test] + fn should_convert_tuples() { + let foo: (String, i64) = RedisValue::Array(vec!["a".into(), 1.into()]).convert().unwrap(); + assert_eq!(foo, ("a".to_owned(), 1)); + } + + #[test] + fn should_convert_array_tuples() { + let foo: Vec<(String, i64)> = RedisValue::Array(vec!["a".into(), 1.into(), "b".into(), 2.into()]) + .convert() + .unwrap(); + assert_eq!(foo, vec![("a".to_owned(), 1), ("b".to_owned(), 2)]); + } +} diff --git a/src/types.rs b/src/types.rs index 2636d67c..bcf295f2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -24,6 +24,8 @@ use std::str; use std::sync::Arc; use tokio::task::JoinHandle; +pub use crate::response::RedisResponse; + #[cfg(feature = "index-map")] use indexmap::{IndexMap, IndexSet}; #[cfg(not(feature = "index-map"))] @@ -972,22 +974,23 @@ pub struct MultipleValues { } impl MultipleValues { - pub(crate) fn new() -> MultipleValues { - MultipleValues { values: Vec::new() } - } - - pub(crate) fn inner(self) -> Vec { + pub fn inner(self) -> Vec { self.values } - pub(crate) fn len(&self) -> usize { + pub fn len(&self) -> usize { self.values.len() } + + /// Convert this a nested `RedisValue`. + pub fn into_values(self) -> RedisValue { + RedisValue::Array(self.values) + } } impl From<()> for MultipleValues { fn from(_: ()) -> Self { - MultipleValues::new() + MultipleValues { values: vec![] } } } @@ -1004,7 +1007,7 @@ where Ok(MultipleValues { values: vec![to!(d)?] }) } } - */ +*/ impl From for MultipleValues where @@ -1475,6 +1478,13 @@ impl<'a> RedisValue { } } RedisValue::String(ref s) => s.parse::().ok(), + RedisValue::Array(ref inner) => { + if inner.len() == 1 { + inner.first().and_then(|v| v.as_u64()) + } else { + None + } + } _ => None, } } @@ -1484,6 +1494,13 @@ impl<'a> RedisValue { match self { RedisValue::Integer(ref i) => Some(*i), RedisValue::String(ref s) => s.parse::().ok(), + RedisValue::Array(ref inner) => { + if inner.len() == 1 { + inner.first().and_then(|v| v.as_i64()) + } else { + None + } + } _ => None, } } @@ -1499,6 +1516,13 @@ impl<'a> RedisValue { } } RedisValue::String(ref s) => s.parse::().ok(), + RedisValue::Array(ref inner) => { + if inner.len() == 1 { + inner.first().and_then(|v| v.as_usize()) + } else { + None + } + } _ => None, } } @@ -1508,6 +1532,13 @@ impl<'a> RedisValue { match self { RedisValue::String(ref s) => utils::redis_string_to_f64(s).ok(), RedisValue::Integer(ref i) => Some(*i as f64), + RedisValue::Array(ref inner) => { + if inner.len() == 1 { + inner.first().and_then(|v| v.as_f64()) + } else { + None + } + } _ => None, } } @@ -1519,6 +1550,13 @@ impl<'a> RedisValue { RedisValue::Bytes(b) => String::from_utf8(b).ok(), RedisValue::Integer(i) => Some(i.to_string()), RedisValue::Queued => Some(QUEUED.to_owned()), + RedisValue::Array(mut inner) => { + if inner.len() == 1 { + inner.pop().and_then(|v| v.into_string()) + } else { + None + } + } _ => None, } } @@ -1585,10 +1623,18 @@ impl<'a> RedisValue { _ => None, }, RedisValue::String(ref s) => match s.as_ref() { - "true" | "TRUE" | "t" | "T" => Some(true), - "false" | "FALSE" | "f" | "F" => Some(false), + "true" | "TRUE" | "t" | "T" | "1" => Some(true), + "false" | "FALSE" | "f" | "F" | "0" => Some(false), _ => None, }, + RedisValue::Null => Some(false), + RedisValue::Array(ref inner) => { + if inner.len() == 1 { + inner.first().and_then(|v| v.as_bool()) + } else { + None + } + } _ => None, } } @@ -1681,6 +1727,28 @@ impl<'a> RedisValue { } } + /// Convert the value to an array of bytes, if possible. + pub fn into_bytes(self) -> Option> { + let v = match self { + RedisValue::String(s) => s.into_bytes(), + RedisValue::Bytes(b) => b, + RedisValue::Null => NULL.as_bytes().to_vec(), + RedisValue::Queued => QUEUED.as_bytes().to_vec(), + RedisValue::Array(mut inner) => { + if inner.len() == 1 { + return inner.pop().and_then(|v| v.into_bytes()); + } else { + return None; + } + } + // TODO maybe rethink this + RedisValue::Integer(i) => i.to_string().into_bytes(), + _ => return None, + }; + + Some(v) + } + /// Convert the value into a `GeoPosition`, if possible. /// /// Null values are returned as `None` to work more easily with the result of the `GEOPOS` command. @@ -1692,6 +1760,37 @@ impl<'a> RedisValue { pub fn take(&mut self) -> RedisValue { mem::replace(self, RedisValue::Null) } + + /// Attempt to convert this value to any value that implements the [RedisResponse](crate::types::RedisResponse) trait. + /// + /// ```rust + /// # use fred::types::RedisValue; + /// # use std::collections::HashMap; + /// let foo: usize = RedisValue::String("123".into()).convert()?; + /// let foo: i64 = RedisValue::String("123".into()).convert()?; + /// let foo: String = RedisValue::String("123".into()).convert()?; + /// let foo: Vec = RedisValue::Bytes(vec![102, 111, 111]).convert()?; + /// let foo: Vec = RedisValue::String("foo".into()).convert()?; + /// let foo: Vec = RedisValue::Array(vec!["a".into(), "b".into()]).convert()?; + /// let foo: HashMap = RedisValue::Array(vec![ + /// "a".into(), 1.into(), + /// "b".into(), 2.into() + /// ]) + /// .convert()?; + /// let foo: (String, i64) = RedisValue::Array(vec!["a".into(), 1.into()]).convert()?; + /// let foo: Vec<(String, i64)> = RedisValue::Array(vec![ + /// "a".into(), 1.into(), + /// "b".into(), 2.into() + /// ]) + /// .convert()?; + /// // ... + /// ``` + pub fn convert(self) -> Result + where + R: RedisResponse, + { + R::from_value(self) + } } impl Hash for RedisValue { @@ -1793,6 +1892,30 @@ impl TryFrom for RedisValue { } } +impl TryFrom for RedisValue { + type Error = RedisError; + + fn try_from(d: u128) -> Result { + if d >= (i64::MAX as u128) { + return Err(RedisError::new(RedisErrorKind::Unknown, "Unsigned integer too large.")); + } + + Ok((d as i64).into()) + } +} + +impl TryFrom for RedisValue { + type Error = RedisError; + + fn try_from(d: i128) -> Result { + if d >= (i64::MAX as i128) { + return Err(RedisError::new(RedisErrorKind::Unknown, "Signed integer too large.")); + } + + Ok((d as i64).into()) + } +} + impl TryFrom for RedisValue { type Error = RedisError; diff --git a/tests/integration/geo/mod.rs b/tests/integration/geo/mod.rs index 0778b904..372dfa54 100644 --- a/tests/integration/geo/mod.rs +++ b/tests/integration/geo/mod.rs @@ -19,7 +19,7 @@ async fn create_fake_data(client: &RedisClient, key: &str) -> Result Result ]; for value in values.into_iter() { - let result = client.geoadd("foo", None, false, value).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.geoadd("foo", None, false, value).await?; + assert_eq!(result, 1); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_usize().unwrap(), 2); + let result: usize = client.zcard("foo").await?; + assert_eq!(result, 2); Ok(()) } @@ -42,13 +42,13 @@ pub async fn should_geoadd_values(client: RedisClient, _: RedisConfig) -> Result pub async fn should_geohash_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let _ = create_fake_data(&client, "foo").await?; - let result = client.geohash("foo", "Palermo").await?; - assert_eq!(result.as_str().unwrap(), "sqc8b49rny0"); - let result = client.geohash("foo", "Catania").await?; - assert_eq!(result.as_str().unwrap(), "sqdtr74hyu0"); + let result: String = client.geohash("foo", "Palermo").await?; + assert_eq!(result, "sqc8b49rny0"); + let result: String = client.geohash("foo", "Catania").await?; + assert_eq!(result, "sqdtr74hyu0"); - let result = client.geohash("foo", vec!["Palermo", "Catania"]).await?; - assert_eq!(result.into_array(), vec!["sqc8b49rny0".into(), "sqdtr74hyu0".into()]); + let result: Vec = client.geohash("foo", vec!["Palermo", "Catania"]).await?; + assert_eq!(result, vec!["sqc8b49rny0", "sqdtr74hyu0"]); Ok(()) } @@ -82,16 +82,16 @@ pub async fn should_geopos_values(client: RedisClient, _: RedisConfig) -> Result pub async fn should_geodist_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let _ = create_fake_data(&client, "foo").await?; - let result = client.geodist("foo", "Palermo", "Catania", None).await?; - assert!(loose_eq(result.as_f64().unwrap(), 166274.1516, 4)); - let result = client + let result: f64 = client.geodist("foo", "Palermo", "Catania", None).await?; + assert!(loose_eq(result, 166274.1516, 4)); + let result: f64 = client .geodist("foo", "Palermo", "Catania", Some(GeoUnit::Kilometers)) .await?; - assert!(loose_eq(result.as_f64().unwrap(), 166.2742, 4)); - let result = client + assert!(loose_eq(result, 166.2742, 4)); + let result: f64 = client .geodist("foo", "Palermo", "Catania", Some(GeoUnit::Miles)) .await?; - assert!(loose_eq(result.as_f64().unwrap(), 103.3182, 4)); + assert!(loose_eq(result, 103.3182, 4)); Ok(()) } diff --git a/tests/integration/hashes/mod.rs b/tests/integration/hashes/mod.rs index 057ed6f8..cf6ec45d 100644 --- a/tests/integration/hashes/mod.rs +++ b/tests/integration/hashes/mod.rs @@ -2,8 +2,7 @@ use fred::client::RedisClient; use fred::error::RedisError; use fred::types::{RedisConfig, RedisMap, RedisValue}; -use std::collections::{HashSet}; - +use std::collections::{HashMap, HashSet}; fn assert_contains<'a, T: Eq + PartialEq>(values: Vec, item: &'a T) { for value in values.iter() { @@ -37,17 +36,17 @@ fn assert_diff_len(values: Vec<&'static str>, value: RedisValue, len: usize) { pub async fn should_hset_and_hget(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.hset("foo", ("a", 1.into())).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.hset("foo", vec![("b", 2.into()), ("c", 3.into())]).await?; - assert_eq!(result.as_i64().unwrap(), 2); + let result: i64 = client.hset("foo", ("a", 1.into())).await?; + assert_eq!(result, 1); + let result: i64 = client.hset("foo", vec![("b", 2.into()), ("c", 3.into())]).await?; + assert_eq!(result, 2); - let a = client.hget("foo", "a").await?; - assert_eq!(a.as_i64().unwrap(), 1); - let b = client.hget("foo", "b").await?; - assert_eq!(b.as_i64().unwrap(), 2); - let c = client.hget("foo", "c").await?; - assert_eq!(c.as_i64().unwrap(), 3); + let a: i64 = client.hget("foo", "a").await?; + assert_eq!(a, 1); + let b: i64 = client.hget("foo", "b").await?; + assert_eq!(b, 2); + let c: i64 = client.hget("foo", "c").await?; + assert_eq!(c, 3); Ok(()) } @@ -55,16 +54,16 @@ pub async fn should_hset_and_hget(client: RedisClient, _: RedisConfig) -> Result pub async fn should_hset_and_hdel(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client + let result: i64 = client .hset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; - assert_eq!(result.as_i64().unwrap(), 3); - let result = client.hdel("foo", vec!["a", "b"]).await?; - assert_eq!(result.as_i64().unwrap(), 2); - let result = client.hdel("foo", "c").await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.hget("foo", "a").await?; - assert!(result.is_null()); + assert_eq!(result, 3); + let result: i64 = client.hdel("foo", vec!["a", "b"]).await?; + assert_eq!(result, 2); + let result: i64 = client.hdel("foo", "c").await?; + assert_eq!(result, 1); + let result: Option = client.hget("foo", "a").await?; + assert!(result.is_none()); Ok(()) } @@ -72,11 +71,11 @@ pub async fn should_hset_and_hdel(client: RedisClient, _: RedisConfig) -> Result pub async fn should_hexists(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.hset("foo", ("a", 1.into())).await?; - let a = client.hexists("foo", "a").await?; - assert!(a.as_bool().unwrap()); - let b = client.hexists("foo", "b").await?; - assert_eq!(b.as_bool().unwrap(), false); + let _: () = client.hset("foo", ("a", 1.into())).await?; + let a: bool = client.hexists("foo", "a").await?; + assert!(a); + let b: bool = client.hexists("foo", "b").await?; + assert!(!b); Ok(()) } @@ -84,18 +83,17 @@ pub async fn should_hexists(client: RedisClient, _: RedisConfig) -> Result<(), R pub async fn should_hgetall(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client + let _: () = client .hset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; - let values = client.hgetall("foo").await?; - let values_map = values.into_map()?; + let values: HashMap = client.hgetall("foo").await?; - assert_eq!(values_map.len(), 3); - let mut expected = RedisMap::new(); - expected.insert("a".into(), "1".into()); - expected.insert("b".into(), "2".into()); - expected.insert("c".into(), "3".into()); - assert_eq!(values_map, expected); + assert_eq!(values.len(), 3); + let mut expected = HashMap::new(); + expected.insert("a".into(), 1); + expected.insert("b".into(), 2); + expected.insert("c".into(), 3); + assert_eq!(values, expected); Ok(()) } @@ -103,10 +101,10 @@ pub async fn should_hgetall(client: RedisClient, _: RedisConfig) -> Result<(), R pub async fn should_hincryby(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.hincrby("foo", "a", 1).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.hincrby("foo", "a", 2).await?; - assert_eq!(result.as_i64().unwrap(), 3); + let result: i64 = client.hincrby("foo", "a", 1).await?; + assert_eq!(result, 1); + let result: i64 = client.hincrby("foo", "a", 2).await?; + assert_eq!(result, 3); Ok(()) } @@ -114,10 +112,10 @@ pub async fn should_hincryby(client: RedisClient, _: RedisConfig) -> Result<(), pub async fn should_hincryby_float(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.hincrbyfloat("foo", "a", 0.5).await?; - assert_eq!(result.as_f64().unwrap(), 0.5); - let result = client.hincrbyfloat("foo", "a", 3.7).await?; - assert_eq!(result.as_f64().unwrap(), 4.2); + let result: f64 = client.hincrbyfloat("foo", "a", 0.5).await?; + assert_eq!(result, 0.5); + let result: f64 = client.hincrbyfloat("foo", "a", 3.7).await?; + assert_eq!(result, 4.2); Ok(()) } @@ -125,7 +123,7 @@ pub async fn should_hincryby_float(client: RedisClient, _: RedisConfig) -> Resul pub async fn should_get_keys(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client + let _: () = client .hset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; @@ -138,16 +136,16 @@ pub async fn should_get_keys(client: RedisClient, _: RedisConfig) -> Result<(), pub async fn should_hmset(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client + let _: () = client .hmset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; - let a = client.hget("foo", "a").await?; - assert_eq!(a.as_i64().unwrap(), 1); - let b = client.hget("foo", "b").await?; - assert_eq!(b.as_i64().unwrap(), 2); - let c = client.hget("foo", "c").await?; - assert_eq!(c.as_i64().unwrap(), 3); + let a: i64 = client.hget("foo", "a").await?; + assert_eq!(a, 1); + let b: i64 = client.hget("foo", "b").await?; + assert_eq!(b, 2); + let c: i64 = client.hget("foo", "c").await?; + assert_eq!(c, 3); Ok(()) } @@ -155,12 +153,12 @@ pub async fn should_hmset(client: RedisClient, _: RedisConfig) -> Result<(), Red pub async fn should_hmget(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client + let _: () = client .hmset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; - let result = client.hmget("foo", vec!["a", "b"]).await?; - assert_eq!(result, RedisValue::Array(vec!["1".into(), "2".into()])); + let result: Vec = client.hmget("foo", vec!["a", "b"]).await?; + assert_eq!(result, vec![1, 2]); Ok(()) } @@ -168,15 +166,15 @@ pub async fn should_hmget(client: RedisClient, _: RedisConfig) -> Result<(), Red pub async fn should_hsetnx(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.hset("foo", ("a", 1.into())).await?; - let result = client.hsetnx("foo", "a", 2).await?; - assert_eq!(result.as_bool().unwrap(), false); - let result = client.hget("foo", "a").await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.hsetnx("foo", "b", 2).await?; - assert!(result.as_bool().unwrap()); - let result = client.hget("foo", "b").await?; - assert_eq!(result.as_i64().unwrap(), 2); + let _: () = client.hset("foo", ("a", 1.into())).await?; + let result: bool = client.hsetnx("foo", "a", 2).await?; + assert_eq!(result, false); + let result: i64 = client.hget("foo", "a").await?; + assert_eq!(result, 1); + let result: bool = client.hsetnx("foo", "b", 2).await?; + assert!(result); + let result: i64 = client.hget("foo", "b").await?; + assert_eq!(result, 2); Ok(()) } @@ -184,19 +182,17 @@ pub async fn should_hsetnx(client: RedisClient, _: RedisConfig) -> Result<(), Re pub async fn should_get_random_field(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client + let _: () = client .hmset("foo", vec![("a", 1.into()), ("b", 2.into()), ("c", 3.into())]) .await?; - let field = client.hrandfield("foo", None).await?; - let field = field.as_str().unwrap(); - assert_contains(vec!["a", "b", "c"], &&**&field); + let field: String = client.hrandfield("foo", None).await?; + assert_contains(vec!["a", "b", "c"], &field.as_str()); let fields = client.hrandfield("foo", Some((2, false))).await?; assert_diff_len(vec!["a", "b", "c"], fields, 1); - let fields = client.hrandfield("foo", Some((2, true))).await?; - let actual = fields.into_map()?; + let actual: HashMap = client.hrandfield("foo", Some((2, true))).await?; assert_eq!(actual.len(), 2); let mut expected = RedisMap::new(); @@ -204,9 +200,9 @@ pub async fn should_get_random_field(client: RedisClient, _: RedisConfig) -> Res expected.insert("b".into(), "2".into()); expected.insert("c".into(), "3".into()); - for (key, value) in actual.inner().into_iter() { - let expected_val = expected.get(&key).unwrap(); - assert_eq!(&value, expected_val); + for (key, value) in actual.into_iter() { + let expected_val: i64 = expected.get(&key).unwrap().clone().convert()?; + assert_eq!(value, expected_val); } Ok(()) @@ -216,10 +212,10 @@ pub async fn should_get_strlen(client: RedisClient, _: RedisConfig) -> Result<() check_null!(client, "foo"); let expected = "abcdefhijklmnopqrstuvwxyz"; - let _ = client.hset("foo", ("a", expected.clone().into())).await?; + let _: () = client.hset("foo", ("a", expected.clone().into())).await?; - let len = client.hstrlen("foo", "a").await?; - assert_eq!(len.as_usize().unwrap(), expected.len()); + let len: usize = client.hstrlen("foo", "a").await?; + assert_eq!(len, expected.len()); Ok(()) } @@ -227,10 +223,9 @@ pub async fn should_get_strlen(client: RedisClient, _: RedisConfig) -> Result<() pub async fn should_get_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.hmset("foo", vec![("a", "1".into()), ("b", "2".into())]).await?; + let _: () = client.hmset("foo", vec![("a", "1".into()), ("b", "2".into())]).await?; - let values = client.hvals("foo").await?; - assert!(values.is_array()); + let values: RedisValue = client.hvals("foo").await?; assert_diff_len(vec!["1", "2"], values, 0); Ok(()) diff --git a/tests/integration/hyperloglog/mod.rs b/tests/integration/hyperloglog/mod.rs index fbe326e8..58997884 100644 --- a/tests/integration/hyperloglog/mod.rs +++ b/tests/integration/hyperloglog/mod.rs @@ -3,10 +3,10 @@ use fred::prelude::*; pub async fn should_pfadd_elements(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.pfadd("foo", vec!["a", "b"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.pfadd("foo", "a").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.pfadd("foo", vec!["a", "b"]).await?; + assert_eq!(result, 1); + let result: i64 = client.pfadd("foo", "a").await?; + assert_eq!(result, 0); Ok(()) } @@ -14,14 +14,14 @@ pub async fn should_pfadd_elements(client: RedisClient, _: RedisConfig) -> Resul pub async fn should_pfcount_elements(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.pfadd("foo", vec!["a", "b", "c"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.pfcount("foo").await?; - assert_eq!(result.as_i64().unwrap(), 3); - let result = client.pfadd("foo", vec!["c", "d", "e"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.pfcount("foo").await?; - assert_eq!(result.as_i64().unwrap(), 5); + let result: i64 = client.pfadd("foo", vec!["a", "b", "c"]).await?; + assert_eq!(result, 1); + let result: i64 = client.pfcount("foo").await?; + assert_eq!(result, 3); + let result: i64 = client.pfadd("foo", vec!["c", "d", "e"]).await?; + assert_eq!(result, 1); + let result: i64 = client.pfcount("foo").await?; + assert_eq!(result, 5); Ok(()) } @@ -31,14 +31,14 @@ pub async fn should_pfmerge_elements(client: RedisClient, _: RedisConfig) -> Res check_null!(client, "bar{1}"); check_null!(client, "baz{1}"); - let result = client.pfadd("foo{1}", vec!["a", "b", "c"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.pfadd("bar{1}", vec!["c", "d", "e"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.pfadd("foo{1}", vec!["a", "b", "c"]).await?; + assert_eq!(result, 1); + let result: i64 = client.pfadd("bar{1}", vec!["c", "d", "e"]).await?; + assert_eq!(result, 1); - let _ = client.pfmerge("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - let result = client.pfcount("baz{1}").await?; - assert_eq!(result.as_i64().unwrap(), 5); + let _: () = client.pfmerge("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + let result: i64 = client.pfcount("baz{1}").await?; + assert_eq!(result, 5); Ok(()) } diff --git a/tests/integration/keys/mod.rs b/tests/integration/keys/mod.rs index 81f9871a..2919430e 100644 --- a/tests/integration/keys/mod.rs +++ b/tests/integration/keys/mod.rs @@ -11,20 +11,20 @@ use tokio::time::sleep; pub async fn should_set_and_get_a_value(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("foo", "bar", None, None, false).await?; - assert_eq!(client.get("foo").await?, "bar".into()); + assert_eq!(client.get::("foo").await?, "bar"); Ok(()) } pub async fn should_set_and_del_a_value(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.set("foo", "bar", None, None, true).await?; - assert!(result.is_null()); + let result: Option = client.set("foo", "bar", None, None, true).await?; + assert!(result.is_none()); - assert_eq!(client.get("foo").await?, "bar".into()); - assert_eq!(client.del("foo").await?.as_i64(), Some(1)); + assert_eq!(client.get::("foo").await?, "bar"); + assert_eq!(client.del::("foo").await?, 1); check_null!(client, "foo"); Ok(()) @@ -33,13 +33,13 @@ pub async fn should_set_and_del_a_value(client: RedisClient, _config: RedisConfi pub async fn should_set_with_get_argument(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("foo", "bar", None, None, false).await?; - let result = client.set("foo", "baz", None, None, true).await?; - assert_eq!(result, RedisValue::String("bar".into())); + let result: String = client.set("foo", "baz", None, None, true).await?; + assert_eq!(result, "bar"); - let result = client.get("foo").await?; - assert_eq!(result, RedisValue::String("baz".into())); + let result: String = client.get("foo").await?; + assert_eq!(result, "baz"); Ok(()) } @@ -47,13 +47,13 @@ pub async fn should_set_with_get_argument(client: RedisClient, _config: RedisCon pub async fn should_incr_and_decr_a_value(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let count = client.incr("foo").await?.as_u64().unwrap(); + let count: u64 = client.incr("foo").await?; assert_eq!(count, 1); - let count = client.incr_by("foo", 2).await?.as_u64().unwrap(); + let count: u64 = client.incr_by("foo", 2).await?; assert_eq!(count, 3); - let count = client.decr("foo").await?.as_u64().unwrap(); + let count: u64 = client.decr("foo").await?; assert_eq!(count, 2); - let count = client.decr_by("foo", 2).await?.as_u64().unwrap(); + let count: u64 = client.decr_by("foo", 2).await?; assert_eq!(count, 0); Ok(()) @@ -62,11 +62,11 @@ pub async fn should_incr_and_decr_a_value(client: RedisClient, _config: RedisCon pub async fn should_incr_by_float(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let count = client.incr_by_float("foo", 1.5).await?.as_f64().unwrap(); + let count: f64 = client.incr_by_float("foo", 1.5).await?; assert_eq!(count, 1.5); - let count = client.incr_by_float("foo", 2.2).await?.as_f64().unwrap(); + let count: f64 = client.incr_by_float("foo", 2.2).await?; assert_eq!(count, 3.7); - let count = client.incr_by_float("foo", -1.2).await?.as_f64().unwrap(); + let count: f64 = client.incr_by_float("foo", -1.2).await?; assert_eq!(count, 2.5); Ok(()) @@ -84,13 +84,13 @@ pub async fn should_mset_a_non_empty_map(client: RedisClient, _config: RedisConf map.insert("c{1}".into(), 3.into()); let _ = client.mset(map).await?; - let a = client.get("a{1}").await?; - let b = client.get("b{1}").await?; - let c = client.get("c{1}").await?; + let a: i64 = client.get("a{1}").await?; + let b: i64 = client.get("b{1}").await?; + let c: i64 = client.get("c{1}").await?; - assert_eq!(a.as_i64().unwrap(), 1); - assert_eq!(b.as_i64().unwrap(), 2); - assert_eq!(c.as_i64().unwrap(), 3); + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); Ok(()) } @@ -102,34 +102,34 @@ pub async fn should_error_mset_empty_map(client: RedisClient, _config: RedisConf pub async fn should_expire_key(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("foo", "bar", None, None, false).await?; - let _ = client.expire("foo", 1).await?; + let _: () = client.expire("foo", 1).await?; sleep(Duration::from_millis(1500)).await; - let foo = client.get("foo").await?; - assert!(foo.is_null()); + let foo: Option = client.get("foo").await?; + assert!(foo.is_none()); Ok(()) } pub async fn should_persist_key(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; + let _: () = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; - let removed = client.persist("foo").await?.as_bool().unwrap(); + let removed: bool = client.persist("foo").await?; assert!(removed); - let ttl = client.ttl("foo").await?; - assert_eq!(ttl.as_i64().unwrap(), -1); + let ttl: i64 = client.ttl("foo").await?; + assert_eq!(ttl, -1); Ok(()) } pub async fn should_check_ttl(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; + let _: () = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; - let ttl = client.ttl("foo").await?.as_i64().unwrap(); + let ttl: i64 = client.ttl("foo").await?; assert!(ttl > 0 && ttl < 6); Ok(()) @@ -137,9 +137,9 @@ pub async fn should_check_ttl(client: RedisClient, _config: RedisConfig) -> Resu pub async fn should_check_pttl(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; + let _: () = client.set("foo", "bar", Some(Expiration::EX(5)), None, false).await?; - let ttl = client.pttl("foo").await?.as_i64().unwrap(); + let ttl: i64 = client.pttl("foo").await?; assert!(ttl > 0 && ttl < 5001); Ok(()) @@ -148,7 +148,7 @@ pub async fn should_check_pttl(client: RedisClient, _config: RedisConfig) -> Res pub async fn should_dump_key(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "abc123", None, None, false).await?; + let _: () = client.set("foo", "abc123", None, None, false).await?; let dump = client.dump("foo").await?; assert!(dump.is_bytes()); @@ -159,27 +159,27 @@ pub async fn should_dump_and_restore_key(client: RedisClient, _: RedisConfig) -> check_null!(client, "foo"); let expected = "abc123"; - let _ = client.set("foo", expected, None, None, false).await?; + let _: () = client.set("foo", expected, None, None, false).await?; let dump = client.dump("foo").await?; - let _ = client.del("foo").await?; + let _: () = client.del("foo").await?; let _ = client.restore("foo", 0, dump, false, false, None, None).await?; - let value = client.get("foo").await?; - assert_eq!(value.as_str().unwrap(), expected); + let value: String = client.get("foo").await?; + assert_eq!(value, expected); Ok(()) } pub async fn should_modify_ranges(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.set("foo", "0123456789", None, None, false).await?; + let _: () = client.set("foo", "0123456789", None, None, false).await?; - let range = client.getrange("foo", 0, 4).await?; - assert_eq!(range.as_str().unwrap(), "01234"); + let range: String = client.getrange("foo", 0, 4).await?; + assert_eq!(range, "01234"); - let _ = client.setrange("foo", 4, "abc").await?; - let value = client.get("foo").await?; - assert_eq!(value.as_str().unwrap(), "0123abc789"); + let _: () = client.setrange("foo", 4, "abc").await?; + let value: String = client.get("foo").await?; + assert_eq!(value, "0123abc789"); Ok(()) } @@ -187,12 +187,12 @@ pub async fn should_modify_ranges(client: RedisClient, _: RedisConfig) -> Result pub async fn should_getset_value(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let value = client.getset("foo", "bar").await?; - assert!(value.is_null()); - let value = client.getset("foo", "baz").await?; - assert_eq!(value.as_str().unwrap(), "bar"); - let value = client.get("foo").await?; - assert_eq!(value.as_str().unwrap(), "baz"); + let value: Option = client.getset("foo", "bar").await?; + assert!(value.is_none()); + let value: String = client.getset("foo", "baz").await?; + assert_eq!(value, "bar"); + let value: String = client.get("foo").await?; + assert_eq!(value, "baz"); Ok(()) } @@ -200,14 +200,14 @@ pub async fn should_getset_value(client: RedisClient, _: RedisConfig) -> Result< pub async fn should_getdel_value(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let value = client.getdel("foo").await?; - assert!(value.is_null()); + let value: Option = client.getdel("foo").await?; + assert!(value.is_none()); - let _ = client.set("foo", "bar", None, None, false).await?; - let value = client.getdel("foo").await?; - assert_eq!(value.as_str().unwrap(), "bar"); - let value = client.get("foo").await?; - assert!(value.is_null()); + let _: () = client.set("foo", "bar", None, None, false).await?; + let value: String = client.getdel("foo").await?; + assert_eq!(value, "bar"); + let value: Option = client.get("foo").await?; + assert!(value.is_none()); Ok(()) } @@ -216,9 +216,9 @@ pub async fn should_get_strlen(client: RedisClient, _: RedisConfig) -> Result<() check_null!(client, "foo"); let expected = "abcdefghijklmnopqrstuvwxyz"; - let _ = client.set("foo", expected, None, None, false).await?; - let len = client.strlen("foo").await?; - assert_eq!(len.as_usize().unwrap(), expected.len()); + let _: () = client.set("foo", expected, None, None, false).await?; + let len: usize = client.strlen("foo").await?; + assert_eq!(len, expected.len()); Ok(()) } @@ -230,16 +230,10 @@ pub async fn should_mget_values(client: RedisClient, _: RedisConfig) -> Result<( let expected: Vec<(&str, RedisValue)> = vec![("a{1}", 1.into()), ("b{1}", 2.into()), ("c{1}", 3.into())]; for (key, value) in expected.iter() { - let _ = client.set(*key, value.clone(), None, None, false).await?; - } - let values = client.mget(vec!["a{1}", "b{1}", "c{1}"]).await?; - - if let RedisValue::Array(values) = values { - // redis does send these back as bulk strings, not integers, which is why `into_integer` exists on RedisValue - assert_eq!(values, vec!["1".into(), "2".into(), "3".into()]); - } else { - return_err!("Expected redis map"); + let _: () = client.set(*key, value.clone(), None, None, false).await?; } + let values: Vec = client.mget(vec!["a{1}", "b{1}", "c{1}"]).await?; + assert_eq!(values, vec![1, 2, 3]); Ok(()) } @@ -251,21 +245,20 @@ pub async fn should_msetnx_values(client: RedisClient, _: RedisConfig) -> Result let expected: Vec<(&str, RedisValue)> = vec![("a{1}", 1.into()), ("b{1}", 2.into())]; // do it first, check they're there - let values = client.msetnx(expected.clone()).await?; - assert_eq!(values.as_i64().unwrap(), 1); - let a = client.get("a{1}").await?; - let b = client.get("b{1}").await?; - assert_eq!(a.as_i64().unwrap(), 1); - assert_eq!(b.as_i64().unwrap(), 2); - - let _ = client.del(vec!["a{1}", "b{1}"]).await?; - let _ = client.set("a{1}", 3, None, None, false).await?; - - let values = client.msetnx(expected.clone()).await?; - assert_eq!(values.as_i64().unwrap(), 0); - assert!(!values.as_bool().unwrap()); - let b = client.get("b{1}").await?; - assert!(b.is_null()); + let values: i64 = client.msetnx(expected.clone()).await?; + assert_eq!(values, 1); + let a: i64 = client.get("a{1}").await?; + let b: i64 = client.get("b{1}").await?; + assert_eq!(a, 1); + assert_eq!(b, 2); + + let _: () = client.del(vec!["a{1}", "b{1}"]).await?; + let _: () = client.set("a{1}", 3, None, None, false).await?; + + let values: i64 = client.msetnx(expected.clone()).await?; + assert_eq!(values, 0); + let b: Option = client.get("b{1}").await?; + assert!(b.is_none()); Ok(()) } @@ -274,21 +267,21 @@ pub async fn should_copy_values(client: RedisClient, _: RedisConfig) -> Result<( check_null!(client, "a{1}"); check_null!(client, "b{1}"); - let _ = client.set("a{1}", "bar", None, None, false).await?; - let result = client.copy("a{1}", "b{1}", None, false).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let _: () = client.set("a{1}", "bar", None, None, false).await?; + let result: i64 = client.copy("a{1}", "b{1}", None, false).await?; + assert_eq!(result, 1); - let b = client.get("b{1}").await?; - assert_eq!(b.as_str().unwrap(), "bar"); + let b: String = client.get("b{1}").await?; + assert_eq!(b, "bar"); - let _ = client.set("a{1}", "baz", None, None, false).await?; - let result = client.copy("a{1}", "b{1}", None, false).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let _: () = client.set("a{1}", "baz", None, None, false).await?; + let result: i64 = client.copy("a{1}", "b{1}", None, false).await?; + assert_eq!(result, 0); - let result = client.copy("a{1}", "b{1}", None, true).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let b = client.get("b{1}").await?; - assert_eq!(b.as_str().unwrap(), "baz"); + let result: i64 = client.copy("a{1}", "b{1}", None, true).await?; + assert_eq!(result, 1); + let b: String = client.get("b{1}").await?; + assert_eq!(b, "baz"); Ok(()) } diff --git a/tests/integration/lists/mod.rs b/tests/integration/lists/mod.rs index a4eebb33..4f78fed4 100644 --- a/tests/integration/lists/mod.rs +++ b/tests/integration/lists/mod.rs @@ -7,7 +7,7 @@ const COUNT: i64 = 10; async fn create_count_data(client: &RedisClient, key: &str) -> Result, RedisError> { let mut values = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { - let _ = client.rpush(key, idx).await?; + let _: () = client.rpush(key, idx).await?; values.push(idx.to_string().into()); } @@ -22,8 +22,8 @@ pub async fn should_blpop_values(client: RedisClient, _: RedisConfig) -> Result< let jh = tokio::spawn(async move { for idx in 0..COUNT { - let result = client.blpop("foo", 30.0).await?; - assert_eq!(result.into_array().pop().unwrap().as_i64().unwrap(), idx); + let mut result: Vec = client.blpop("foo", 30.0).await?; + assert_eq!(result.pop().unwrap().as_i64().unwrap(), idx); } Ok::<_, RedisError>(()) @@ -32,8 +32,8 @@ pub async fn should_blpop_values(client: RedisClient, _: RedisConfig) -> Result< for idx in 0..COUNT { // the assertion below checks the length of the list, so we have to make sure not to push faster than elements are removed sleep(Duration::from_millis(50)).await; - let result = publisher.rpush("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = publisher.rpush("foo", idx).await?; + assert_eq!(result, 1); } let _ = jh.await?; @@ -48,8 +48,8 @@ pub async fn should_brpop_values(client: RedisClient, _: RedisConfig) -> Result< let jh = tokio::spawn(async move { for idx in 0..COUNT { - let result = client.brpop("foo", 30.0).await?; - assert_eq!(result.into_array().pop().unwrap().as_i64().unwrap(), idx); + let mut result: Vec = client.brpop("foo", 30.0).await?; + assert_eq!(result.pop().unwrap().as_i64().unwrap(), idx); } Ok::<_, RedisError>(()) @@ -58,8 +58,8 @@ pub async fn should_brpop_values(client: RedisClient, _: RedisConfig) -> Result< for idx in 0..COUNT { // the assertion below checks the length of the list, so we have to make sure not to push faster than elements are removed sleep(Duration::from_millis(50)).await; - let result = publisher.lpush("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = publisher.lpush("foo", idx).await?; + assert_eq!(result, 1); } let _ = jh.await?; @@ -74,22 +74,22 @@ pub async fn should_brpoplpush_values(client: RedisClient, _: RedisConfig) -> Re let jh = tokio::spawn(async move { for idx in 0..COUNT { - let result = client.brpoplpush("foo{1}", "bar{1}", 30.0).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.brpoplpush("foo{1}", "bar{1}", 30.0).await?; + assert_eq!(result, idx); } Ok::<_, RedisError>(()) }); for idx in 0..COUNT { - let result = publisher.lpush("foo{1}", idx).await?; - assert!(result.as_i64().unwrap() > 0); + let result: i64 = publisher.lpush("foo{1}", idx).await?; + assert!(result > 0); } let _ = jh.await?; for idx in 0..COUNT { - let result = publisher.rpop("bar{1}", None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = publisher.rpop("bar{1}", None).await?; + assert_eq!(result, idx); } Ok(()) @@ -103,24 +103,24 @@ pub async fn should_blmove_values(client: RedisClient, _: RedisConfig) -> Result let jh = tokio::spawn(async move { for idx in 0..COUNT { - let result = client + let result: i64 = client .blmove("foo{1}", "bar{1}", LMoveDirection::Right, LMoveDirection::Left, 30.0) .await?; - assert_eq!(result.as_i64().unwrap(), idx); + assert_eq!(result, idx); } Ok::<_, RedisError>(()) }); for idx in 0..COUNT { - let result = publisher.lpush("foo{1}", idx).await?; - assert!(result.as_i64().unwrap() > 0); + let result: i64 = publisher.lpush("foo{1}", idx).await?; + assert!(result > 0); } let _ = jh.await?; for idx in 0..COUNT { - let result = publisher.rpop("bar{1}", None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = publisher.rpop("bar{1}", None).await?; + assert_eq!(result, idx); } Ok(()) @@ -130,7 +130,7 @@ pub async fn should_lindex_values(client: RedisClient, _: RedisConfig) -> Result let expected = create_count_data(&client, "foo").await?; for (idx, expected_value) in expected.into_iter().enumerate() { - let result = client.lindex("foo", idx as i64).await?; + let result: RedisValue = client.lindex("foo", idx as i64).await?; assert_eq!(result, expected_value); } @@ -138,20 +138,20 @@ pub async fn should_lindex_values(client: RedisClient, _: RedisConfig) -> Result } pub async fn should_linsert_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let result = client.linsert("foo", ListLocation::Before, 1, 0).await?; - assert_eq!(result.as_usize().unwrap(), 0); - let result = client.llen("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.linsert("foo", ListLocation::Before, 1, 0).await?; + assert_eq!(result, 0); + let result: usize = client.llen("foo").await?; + assert_eq!(result, 0); - let _ = client.lpush("foo", 0).await?; + let _: () = client.lpush("foo", 0).await?; let mut expected: Vec = vec!["0".into()]; for idx in 1..COUNT { - let result = client.linsert("foo", ListLocation::After, idx - 1, idx).await?; - assert_eq!(result.as_i64().unwrap(), idx + 1); + let result: i64 = client.linsert("foo", ListLocation::After, idx - 1, idx).await?; + assert_eq!(result, idx + 1); expected.push(idx.to_string().into()); } - let values = client.lrange("foo", 0, COUNT).await?; - assert_eq!(values.into_array(), expected); + let values: Vec = client.lrange("foo", 0, COUNT).await?; + assert_eq!(values, expected); Ok(()) } @@ -160,13 +160,13 @@ pub async fn should_lpop_values(client: RedisClient, _: RedisConfig) -> Result<( let expected = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.lpop("foo", None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.lpop("foo", None).await?; + assert_eq!(result, idx); } let _ = create_count_data(&client, "foo").await?; - let result = client.lpop("foo", Some(COUNT as usize)).await?; - assert_eq!(result.into_array(), expected); + let result: Vec = client.lpop("foo", Some(COUNT as usize)).await?; + assert_eq!(result, expected); Ok(()) } @@ -175,26 +175,26 @@ pub async fn should_lpos_values(client: RedisClient, _: RedisConfig) -> Result<( let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.lpos("foo", idx, None, None, None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.lpos("foo", idx, None, None, None).await?; + assert_eq!(result, idx); } let _ = create_count_data(&client, "foo").await?; let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.lpos("foo", idx, Some(2), None, None).await?; - assert_eq!(result, (idx + COUNT).into()); - let result = client.lpos("foo", idx, Some(3), None, None).await?; - assert_eq!(result, (idx + COUNT * 2).into()); - - let result = client.lpos("foo", idx, None, Some(2), None).await?; - let expected = vec![idx.into(), (idx + COUNT).into()]; - assert_eq!(result.into_array(), expected); - - let result = client.lpos("foo", idx, None, Some(3), None).await?; - let expected = vec![idx.into(), (idx + COUNT).into(), (idx + COUNT * 2).into()]; - assert_eq!(result.into_array(), expected); + let result: i64 = client.lpos("foo", idx, Some(2), None, None).await?; + assert_eq!(result, idx + COUNT); + let result: i64 = client.lpos("foo", idx, Some(3), None, None).await?; + assert_eq!(result, idx + COUNT * 2); + + let result: Vec = client.lpos("foo", idx, None, Some(2), None).await?; + let expected = vec![idx, (idx + COUNT)]; + assert_eq!(result, expected); + + let result: Vec = client.lpos("foo", idx, None, Some(3), None).await?; + let expected = vec![idx, (idx + COUNT), (idx + COUNT * 2)]; + assert_eq!(result, expected); } Ok(()) @@ -202,30 +202,30 @@ pub async fn should_lpos_values(client: RedisClient, _: RedisConfig) -> Result<( pub async fn should_lpush_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { - let result = client.lpush("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), idx + 1); - let result = client.lrange("foo", 0, 0).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.lpush("foo", idx).await?; + assert_eq!(result, idx + 1); + let result: i64 = client.lrange("foo", 0, 0).await?; + assert_eq!(result, idx); } - let result = client.llen("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + let result: i64 = client.llen("foo").await?; + assert_eq!(result, COUNT); Ok(()) } pub async fn should_lpushx_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let result = client.lpushx("foo", 0).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.lpushx("foo", 0).await?; + assert_eq!(result, 0); - let _ = client.lpush("foo", 0).await?; + let _: () = client.lpush("foo", 0).await?; for idx in 0..COUNT { - let result = client.lpushx("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), idx + 2); - let result = client.lrange("foo", 0, 0).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.lpushx("foo", idx).await?; + assert_eq!(result, idx + 2); + let result: i64 = client.lrange("foo", 0, 0).await?; + assert_eq!(result, idx); } - let result = client.llen("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT + 1); + let result: i64 = client.llen("foo").await?; + assert_eq!(result, COUNT + 1); Ok(()) } @@ -233,12 +233,12 @@ pub async fn should_lpushx_values(client: RedisClient, _: RedisConfig) -> Result pub async fn should_lrange_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let expected = create_count_data(&client, "foo").await?; - let result = client.lrange("foo", 0, COUNT).await?; - assert_eq!(result.into_array(), expected); + let result: Vec = client.lrange("foo", 0, COUNT).await?; + assert_eq!(result, expected); for idx in 0..COUNT { - let result = client.lrange("foo", idx, idx).await?; - assert_eq!(result.as_i64().unwrap(), idx.into()); + let result: i64 = client.lrange("foo", idx, idx).await?; + assert_eq!(result, idx.into()); } Ok(()) @@ -247,34 +247,34 @@ pub async fn should_lrange_values(client: RedisClient, _: RedisConfig) -> Result pub async fn should_lrem_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.lrem("foo", 1, idx).await?; - assert_eq!(result.as_usize().unwrap(), 1); + let result: usize = client.lrem("foo", 1, idx).await?; + assert_eq!(result, 1); } - let result = client.llen("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.llen("foo").await?; + assert_eq!(result, 0); let _ = create_count_data(&client, "foo").await?; let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.lrem("foo", 2, idx).await?; - assert_eq!(result.as_usize().unwrap(), 2); + let result: usize = client.lrem("foo", 2, idx).await?; + assert_eq!(result, 2); } - let result = client.llen("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.llen("foo").await?; + assert_eq!(result, 0); Ok(()) } pub async fn should_lset_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - assert!(client.lset("foo", 1, 0).await.is_err()); + assert!(client.lset::("foo", 1, 0).await.is_err()); let mut expected = create_count_data(&client, "foo").await?; expected.reverse(); for idx in 0..COUNT { - let _ = client.lset("foo", idx, COUNT - (idx + 1)).await?; + let _: () = client.lset("foo", idx, COUNT - (idx + 1)).await?; } - let result = client.lrange("foo", 0, COUNT).await?; - assert_eq!(result.into_array(), expected); + let result: Vec = client.lrange("foo", 0, COUNT).await?; + assert_eq!(result, expected); Ok(()) } @@ -282,16 +282,16 @@ pub async fn should_lset_values(client: RedisClient, _: RedisConfig) -> Result<( pub async fn should_ltrim_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let expected = create_count_data(&client, "foo").await?; - let _ = client.ltrim("foo", 0, COUNT).await?; - let result = client.lrange("foo", 0, COUNT).await?; - assert_eq!(result.into_array(), expected); + let _: () = client.ltrim("foo", 0, COUNT).await?; + let result: Vec = client.lrange("foo", 0, COUNT).await?; + assert_eq!(result, expected); for idx in 0..COUNT { - let _ = client.ltrim("foo", 0, idx).await?; - let result = client.lrange("foo", 0, COUNT).await?; - assert_eq!(result.into_array(), expected[0..(idx + 1) as usize]); + let _: () = client.ltrim("foo", 0, idx).await?; + let result: Vec = client.lrange("foo", 0, COUNT).await?; + assert_eq!(result, expected[0..(idx + 1) as usize]); - let _ = client.del("foo").await?; + let _: () = client.del("foo").await?; let _ = create_count_data(&client, "foo").await?; } @@ -303,25 +303,25 @@ pub async fn should_rpop_values(client: RedisClient, _: RedisConfig) -> Result<( expected.reverse(); for idx in 0..COUNT { - let result = client.rpop("foo", None).await?; - assert_eq!(result.as_i64().unwrap(), COUNT - (idx + 1)); + let result: i64 = client.rpop("foo", None).await?; + assert_eq!(result, COUNT - (idx + 1)); } let _ = create_count_data(&client, "foo").await?; - let result = client.rpop("foo", Some(COUNT as usize)).await?; - assert_eq!(result.into_array(), expected); + let result: Vec = client.rpop("foo", Some(COUNT as usize)).await?; + assert_eq!(result, expected); Ok(()) } pub async fn should_rpoplpush_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { - let result = client.lpush("foo{1}", idx).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.rpoplpush("foo{1}", "bar{1}").await?; - assert_eq!(result.as_i64().unwrap(), idx); - let result = client.rpop("bar{1}", None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.lpush("foo{1}", idx).await?; + assert_eq!(result, 1); + let result: i64 = client.rpoplpush("foo{1}", "bar{1}").await?; + assert_eq!(result, idx); + let result: i64 = client.rpop("bar{1}", None).await?; + assert_eq!(result, idx); } Ok(()) @@ -329,14 +329,14 @@ pub async fn should_rpoplpush_values(client: RedisClient, _: RedisConfig) -> Res pub async fn should_lmove_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { - let result = client.lpush("foo{1}", idx).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client + let result: i64 = client.lpush("foo{1}", idx).await?; + assert_eq!(result, 1); + let result: i64 = client .lmove("foo{1}", "bar{1}", LMoveDirection::Right, LMoveDirection::Left) .await?; - assert_eq!(result.as_i64().unwrap(), idx); - let result = client.rpop("bar{1}", None).await?; - assert_eq!(result.as_i64().unwrap(), idx); + assert_eq!(result, idx); + let result: i64 = client.rpop("bar{1}", None).await?; + assert_eq!(result, idx); } Ok(()) @@ -344,30 +344,30 @@ pub async fn should_lmove_values(client: RedisClient, _: RedisConfig) -> Result< pub async fn should_rpush_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { - let result = client.rpush("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), idx + 1); - let result = client.lrange("foo", -1, -1).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.rpush("foo", idx).await?; + assert_eq!(result, idx + 1); + let result: i64 = client.lrange("foo", -1, -1).await?; + assert_eq!(result, idx); } - let result = client.llen("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + let result: i64 = client.llen("foo").await?; + assert_eq!(result, COUNT); Ok(()) } pub async fn should_rpushx_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let result = client.rpushx("foo", 0).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.rpushx("foo", 0).await?; + assert_eq!(result, 0); - let _ = client.rpush("foo", 0).await?; + let _: () = client.rpush("foo", 0).await?; for idx in 0..COUNT { - let result = client.rpushx("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), idx + 2); - let result = client.lrange("foo", -1, -1).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.rpushx("foo", idx).await?; + assert_eq!(result, idx + 2); + let result: i64 = client.lrange("foo", -1, -1).await?; + assert_eq!(result, idx); } - let result = client.llen("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT + 1); + let result: i64 = client.llen("foo").await?; + assert_eq!(result, COUNT + 1); Ok(()) } diff --git a/tests/integration/lua/mod.rs b/tests/integration/lua/mod.rs index 4dc79325..81c4c82c 100644 --- a/tests/integration/lua/mod.rs +++ b/tests/integration/lua/mod.rs @@ -4,7 +4,7 @@ use fred::prelude::*; static ECHO_SCRIPT: &'static str = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"; static GET_SCRIPT: &'static str = "return redis.call('get', KEYS[1])"; -pub async fn load_script(client: &RedisClient, script: &str) -> Result { +pub async fn load_script(client: &RedisClient, script: &str) -> Result { if client.is_clustered() { client.script_load_cluster(script).await } else { @@ -23,7 +23,7 @@ pub async fn flush_scripts(client: &RedisClient) -> Result<(), RedisError> { pub async fn should_load_script(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let script_hash = util::sha1_hash(ECHO_SCRIPT); let hash = client.script_load(ECHO_SCRIPT).await?; - assert_eq!(hash.as_str().unwrap(), script_hash); + assert_eq!(hash, script_hash); Ok(()) } @@ -31,20 +31,16 @@ pub async fn should_load_script(client: RedisClient, _: RedisConfig) -> Result<( pub async fn should_load_script_cluster(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let script_hash = util::sha1_hash(ECHO_SCRIPT); let hash = client.script_load_cluster(ECHO_SCRIPT).await?; - assert_eq!(hash.as_str().unwrap(), script_hash); + assert_eq!(hash, script_hash); Ok(()) } pub async fn should_evalsha_echo_script(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let hash = load_script(&client, ECHO_SCRIPT).await?; - let hash = hash.as_str().unwrap().to_owned(); - let result = client.evalsha(hash, vec!["a{1}", "b{1}"], vec!["c{1}", "d{1}"]).await?; - assert_eq!( - result.into_array(), - vec!["a{1}".into(), "b{1}".into(), "c{1}".into(), "d{1}".into()] - ); + let result: Vec = client.evalsha(hash, vec!["a{1}", "b{1}"], vec!["c{1}", "d{1}"]).await?; + assert_eq!(result, vec!["a{1}", "b{1}", "c{1}", "d{1}"]); let _ = flush_scripts(&client).await?; Ok(()) @@ -53,46 +49,43 @@ pub async fn should_evalsha_echo_script(client: RedisClient, _: RedisConfig) -> pub async fn should_evalsha_get_script(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let script_hash = util::sha1_hash(GET_SCRIPT); let hash = load_script(&client, GET_SCRIPT).await?; - assert_eq!(hash.as_str().unwrap(), script_hash); + assert_eq!(hash, script_hash); - let result = client.evalsha(&script_hash, vec!["foo"], ()).await?; - assert!(result.is_null()); + let result: Option = client.evalsha(&script_hash, vec!["foo"], ()).await?; + assert!(result.is_none()); - let _ = client.set("foo", "bar", None, None, false).await?; - let result = client.evalsha(&script_hash, vec!["foo"], ()).await?; - assert_eq!(result.as_str().unwrap(), "bar"); + let _: () = client.set("foo", "bar", None, None, false).await?; + let result: String = client.evalsha(&script_hash, vec!["foo"], ()).await?; + assert_eq!(result, "bar"); let _ = flush_scripts(&client).await?; Ok(()) } pub async fn should_eval_echo_script(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let result = client + let result: Vec = client .eval(ECHO_SCRIPT, vec!["a{1}", "b{1}"], vec!["c{1}", "d{1}"]) .await?; - assert_eq!( - result.into_array(), - vec!["a{1}".into(), "b{1}".into(), "c{1}".into(), "d{1}".into()] - ); + assert_eq!(result, vec!["a{1}", "b{1}", "c{1}", "d{1}"]); let _ = flush_scripts(&client).await?; Ok(()) } pub async fn should_eval_get_script(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let result = client.eval(GET_SCRIPT, vec!["foo"], ()).await?; - assert!(result.is_null()); + let result: Option = client.eval(GET_SCRIPT, vec!["foo"], ()).await?; + assert!(result.is_none()); let hash = util::sha1_hash(GET_SCRIPT); - let result = client.evalsha(&hash, vec!["foo"], ()).await?; - assert!(result.is_null()); + let result: Option = client.evalsha(&hash, vec!["foo"], ()).await?; + assert!(result.is_none()); - let _ = client.set("foo", "bar", None, None, false).await?; - let result = client.eval(GET_SCRIPT, vec!["foo"], ()).await?; - assert_eq!(result.as_str().unwrap(), "bar"); + let _: () = client.set("foo", "bar", None, None, false).await?; + let result: String = client.eval(GET_SCRIPT, vec!["foo"], ()).await?; + assert_eq!(result, "bar"); - let result = client.evalsha(&hash, vec!["foo"], ()).await?; - assert_eq!(result.as_str().unwrap(), "bar"); + let result: String = client.evalsha(&hash, vec!["foo"], ()).await?; + assert_eq!(result, "bar"); let _ = flush_scripts(&client).await?; Ok(()) diff --git a/tests/integration/memory/mod.rs b/tests/integration/memory/mod.rs index 98103cc5..2a751c1a 100644 --- a/tests/integration/memory/mod.rs +++ b/tests/integration/memory/mod.rs @@ -23,7 +23,7 @@ pub async fn should_run_memory_stats(client: RedisClient, _: RedisConfig) -> Res } pub async fn should_run_memory_usage(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let _ = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("foo", "bar", None, None, false).await?; let amt = client.memory_usage("foo", None).await?; assert!(amt.unwrap() > 0); diff --git a/tests/integration/multi/mod.rs b/tests/integration/multi/mod.rs index b7bca213..2c62f0d8 100644 --- a/tests/integration/multi/mod.rs +++ b/tests/integration/multi/mod.rs @@ -1,46 +1,41 @@ use fred::client::RedisClient; use fred::error::RedisError; -use fred::types::{RedisConfig, RedisValue}; +use fred::types::RedisConfig; pub async fn should_run_get_set_trx(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { let trx = client.multi(true).await?; - let _r1 = trx.set("foo", "bar", None, None, false).await?; - let _r2 = trx.get("foo").await?; - let results = trx.exec().await?; + let _r1: () = trx.set("foo", "bar", None, None, false).await?; + let _r2: () = trx.get("foo").await?; + let results: Vec = trx.exec().await?; - assert_eq!( - results, - vec![RedisValue::new_ok(), RedisValue::from("bar")] - .into_iter() - .collect() - ); + assert_eq!(results, vec!["OK", "bar"]); Ok(()) } pub async fn should_run_error_get_set_trx(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { - let _ = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("foo", "bar", None, None, false).await?; let trx = client.multi(true).await?; - let _ = trx.incr("foo").await?; - let _ = trx.exec().await?; + let _: () = trx.incr("foo").await?; + let _: () = trx.exec().await?; Ok(()) } pub async fn should_fail_with_hashslot_error(client: RedisClient, _config: RedisConfig) -> Result<(), RedisError> { let trx = client.multi(true).await?; - let _ = client.set("foo", "bar", None, None, false).await?; - let _ = client.set("bar", "baz", None, None, false).await?; - let _ = trx.exec().await?; + let _: () = client.set("foo", "bar", None, None, false).await?; + let _: () = client.set("bar", "baz", None, None, false).await?; + let _: () = trx.exec().await?; Ok(()) } pub async fn should_fail_with_blocking_cmd(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let trx = client.multi(true).await?; - let _ = client.blpop("foo", 100.0).await?; - let _ = trx.exec().await?; + let _: () = client.blpop("foo", 100.0).await?; + let _: () = trx.exec().await?; Ok(()) } diff --git a/tests/integration/other/mod.rs b/tests/integration/other/mod.rs index 92aa62e7..0bc8a58d 100644 --- a/tests/integration/other/mod.rs +++ b/tests/integration/other/mod.rs @@ -18,7 +18,7 @@ pub async fn should_automatically_unblock(_: RedisClient, mut config: RedisConfi let _ = unblock_client.ping().await; }); - let result = client.blpop("foo", 60.0).await; + let result = client.blpop::<(), _>("foo", 60.0).await; assert!(result.is_err()); assert_ne!(*result.unwrap_err().kind(), RedisErrorKind::Timeout); Ok(()) @@ -32,11 +32,13 @@ pub async fn should_manually_unblock(client: RedisClient, _: RedisConfig) -> Res sleep(Duration::from_secs(1)).await; for (_, id) in connections_ids.into_iter() { - let _ = unblock_client.client_unblock(id, Some(ClientUnblockFlag::Error)).await; + let _ = unblock_client + .client_unblock::<(), _>(id, Some(ClientUnblockFlag::Error)) + .await; } }); - let result = client.blpop("foo", 60.0).await; + let result = client.blpop::<(), _>("foo", 60.0).await; assert!(result.is_err()); assert_ne!(*result.unwrap_err().kind(), RedisErrorKind::Timeout); Ok(()) @@ -59,7 +61,7 @@ pub async fn should_error_when_blocked(_: RedisClient, mut config: RedisConfig) let _ = error_client.unblock_self(None).await; }); - let result = client.blpop("foo", 60.0).await; + let result = client.blpop::<(), _>("foo", 60.0).await; assert!(result.is_err()); Ok(()) } @@ -116,13 +118,13 @@ pub async fn should_run_flushall_cluster(client: RedisClient, _: RedisConfig) -> let count: i64 = 200; for idx in 0..count { - let _ = client.set(format!("foo-{}", idx), idx, None, None, false).await?; + let _: () = client.set(format!("foo-{}", idx), idx, None, None, false).await?; } let _ = client.flushall_cluster().await?; for idx in 0..count { - let value = client.get(format!("foo-{}", idx)).await?; - assert!(value.is_null()); + let value: Option = client.get(format!("foo-{}", idx)).await?; + assert!(value.is_none()); } Ok(()) diff --git a/tests/integration/pubsub/mod.rs b/tests/integration/pubsub/mod.rs index 7f3ce717..824aaf62 100644 --- a/tests/integration/pubsub/mod.rs +++ b/tests/integration/pubsub/mod.rs @@ -33,7 +33,7 @@ pub async fn should_publish_and_recv_messages(client: RedisClient, _: RedisConfi let mut count = 0; while count < NUM_MESSAGES { if let Some((channel, message)) = message_stream.next().await { - let message = message.as_str().unwrap(); + let message: String = message.convert().unwrap(); assert_eq!(CHANNEL1, channel); if ASSERT_COUNT { @@ -48,7 +48,7 @@ pub async fn should_publish_and_recv_messages(client: RedisClient, _: RedisConfi for idx in 0..NUM_MESSAGES + EXTRA_MESSAGES { // https://redis.io/commands/publish#return-value - let _ = client.publish(CHANNEL1, format!("{}-{}", FAKE_MESSAGE, idx)).await?; + let _: () = client.publish(CHANNEL1, format!("{}-{}", FAKE_MESSAGE, idx)).await?; // pubsub messages may arrive out of order due to cross-cluster broadcasting sleep(Duration::from_millis(50)).await; @@ -74,7 +74,7 @@ pub async fn should_psubscribe_and_recv_messages(client: RedisClient, _: RedisCo let mut count = 0; while count < NUM_MESSAGES { if let Some((channel, message)) = message_stream.next().await { - let message = message.as_str().unwrap(); + let message: String = message.convert().unwrap(); assert!(subscriber_channels.contains(&channel.as_str())); if ASSERT_COUNT { @@ -91,7 +91,7 @@ pub async fn should_psubscribe_and_recv_messages(client: RedisClient, _: RedisCo let channel = channels[idx as usize % channels.len()]; // https://redis.io/commands/publish#return-value - let _ = client.publish(channel, format!("{}-{}", FAKE_MESSAGE, idx)).await?; + let _: () = client.publish(channel, format!("{}-{}", FAKE_MESSAGE, idx)).await?; // pubsub messages may arrive out of order due to cross-cluster broadcasting sleep(Duration::from_millis(50)).await; diff --git a/tests/integration/server/mod.rs b/tests/integration/server/mod.rs index 1de8c704..7d7ea936 100644 --- a/tests/integration/server/mod.rs +++ b/tests/integration/server/mod.rs @@ -7,18 +7,18 @@ pub async fn should_flushall(client: RedisClient, _: RedisConfig) -> Result<(), if client.is_clustered() { let _ = client.flushall_cluster().await?; } else { - let _ = client.flushall(false).await?; + let _: () = client.flushall(false).await?; }; - let result = client.get("foo{1}").await?; - assert!(result.is_null()); + let result: Option = client.get("foo{1}").await?; + assert!(result.is_none()); Ok(()) } pub async fn should_read_server_info(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let info = client.info(None).await?; - assert!(info.as_str().is_some()); + let info: Option = client.info(None).await?; + assert!(info.is_some()); Ok(()) } @@ -36,27 +36,27 @@ pub async fn should_run_custom_command(_client: RedisClient, _: RedisConfig) -> } pub async fn should_read_last_save(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let lastsave = client.lastsave().await?; - assert!(lastsave.as_i64().is_some()); + let lastsave: Option = client.lastsave().await?; + assert!(lastsave.is_some()); Ok(()) } pub async fn should_read_db_size(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..50 { - let _ = client.set(format!("foo-{}", idx), idx, None, None, false).await?; + let _: () = client.set(format!("foo-{}", idx), idx, None, None, false).await?; } // this is tricky to assert b/c the dbsize command isnt linked to a specific server in the cluster, hence the loop above - let db_size = client.dbsize().await?; - assert!(db_size.as_i64().unwrap() > 0); + let db_size: i64 = client.dbsize().await?; + assert!(db_size > 0); Ok(()) } pub async fn should_start_bgsave(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { - let save_result = client.bgsave().await?; - assert_eq!(save_result.as_str().unwrap(), "Background saving started"); + let save_result: String = client.bgsave().await?; + assert_eq!(save_result, "Background saving started"); // need to ensure this finishes before it runs again or it'll return an error sleep(Duration::from_millis(1000)).await; diff --git a/tests/integration/sets/mod.rs b/tests/integration/sets/mod.rs index 5b6f71bb..9bcee022 100644 --- a/tests/integration/sets/mod.rs +++ b/tests/integration/sets/mod.rs @@ -1,9 +1,6 @@ use fred::prelude::*; use std::collections::HashSet; -#[cfg(feature = "index-map")] -use indexmap::set::IndexSet; - fn vec_to_set(data: Vec) -> HashSet { let mut out = HashSet::with_capacity(data.len()); for value in data.into_iter() { @@ -12,13 +9,14 @@ fn vec_to_set(data: Vec) -> HashSet { out } +/* #[cfg(feature = "index-map")] fn sets_eq(lhs: &IndexSet, rhs: &HashSet) -> bool { let lhs: HashSet = lhs.iter().map(|v| v.clone()).collect(); &lhs == rhs } + */ -#[cfg(not(feature = "index-map"))] fn sets_eq(lhs: &HashSet, rhs: &HashSet) -> bool { lhs == rhs } @@ -26,12 +24,12 @@ fn sets_eq(lhs: &HashSet, rhs: &HashSet) -> bool { pub async fn should_sadd_elements(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.sadd("foo", "a").await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.sadd("foo", vec!["b", "c"]).await?; - assert_eq!(result.as_i64().unwrap(), 2); - let result = client.sadd("foo", vec!["c", "d"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.sadd("foo", "a").await?; + assert_eq!(result, 1); + let result: i64 = client.sadd("foo", vec!["b", "c"]).await?; + assert_eq!(result, 2); + let result: i64 = client.sadd("foo", vec!["c", "d"]).await?; + assert_eq!(result, 1); Ok(()) } @@ -39,13 +37,13 @@ pub async fn should_sadd_elements(client: RedisClient, _: RedisConfig) -> Result pub async fn should_scard_elements(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.scard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.scard("foo").await?; + assert_eq!(result, 0); - let result = client.sadd("foo", vec!["1", "2", "3", "4", "5"]).await?; - assert_eq!(result.as_i64().unwrap(), 5); - let result = client.scard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 5); + let result: i64 = client.sadd("foo", vec!["1", "2", "3", "4", "5"]).await?; + assert_eq!(result, 5); + let result: i64 = client.scard("foo").await?; + assert_eq!(result, 5); Ok(()) } @@ -54,15 +52,11 @@ pub async fn should_sdiff_elements(client: RedisClient, _: RedisConfig) -> Resul check_null!(client, "foo{1}"); check_null!(client, "bar{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sdiff(vec!["foo{1}", "bar{1}"]).await?; - - assert!(sets_eq( - &result.into_set().unwrap(), - &vec_to_set(vec!["1".into(), "2".into()]) - )); + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: HashSet = client.sdiff(vec!["foo{1}", "bar{1}"]).await?; + assert!(sets_eq(&result, &vec_to_set(vec!["1".into(), "2".into()]))); Ok(()) } @@ -71,17 +65,13 @@ pub async fn should_sdiffstore_elements(client: RedisClient, _: RedisConfig) -> check_null!(client, "bar{1}"); check_null!(client, "baz{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - assert_eq!(result.as_i64().unwrap(), 2); - let result = client.smembers("baz{1}").await?; - - assert!(sets_eq( - &result.into_set().unwrap(), - &vec_to_set(vec!["1".into(), "2".into()]) - )); + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: i64 = client.sdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + assert_eq!(result, 2); + let result: HashSet = client.smembers("baz{1}").await?; + assert!(sets_eq(&result, &vec_to_set(vec!["1".into(), "2".into()]))); Ok(()) } @@ -90,12 +80,12 @@ pub async fn should_sinter_elements(client: RedisClient, _: RedisConfig) -> Resu check_null!(client, "bar{1}"); check_null!(client, "baz{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sinter(vec!["foo{1}", "bar{1}"]).await?; + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: HashSet = client.sinter(vec!["foo{1}", "bar{1}"]).await?; assert!(sets_eq( - &result.into_set().unwrap(), + &result, &vec_to_set(vec!["3".into(), "4".into(), "5".into(), "6".into()]) )); @@ -107,14 +97,14 @@ pub async fn should_sinterstore_elements(client: RedisClient, _: RedisConfig) -> check_null!(client, "bar{1}"); check_null!(client, "baz{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sinterstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - assert_eq!(result.as_i64().unwrap(), 4); - let result = client.smembers("baz{1}").await?; + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: i64 = client.sinterstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + assert_eq!(result, 4); + let result: HashSet = client.smembers("baz{1}").await?; assert!(sets_eq( - &result.into_set().unwrap(), + &result, &vec_to_set(vec!["3".into(), "4".into(), "5".into(), "6".into()]) )); @@ -125,10 +115,10 @@ pub async fn should_check_sismember(client: RedisClient, _: RedisConfig) -> Resu check_null!(client, "foo"); let _ = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; - let result = client.sismember("foo", 1).await?; - assert_eq!(result.as_bool().unwrap(), true); - let result = client.sismember("foo", 7).await?; - assert_eq!(result.as_bool().unwrap(), false); + let result: bool = client.sismember("foo", 1).await?; + assert!(result); + let result: bool = client.sismember("foo", 7).await?; + assert_eq!(result, false); Ok(()) } @@ -137,14 +127,13 @@ pub async fn should_check_smismember(client: RedisClient, _: RedisConfig) -> Res check_null!(client, "foo"); let _ = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; - let result = client.smismember("foo", vec![1, 2, 7]).await?; - let result = result.into_array(); - assert_eq!(result[0].as_bool().unwrap(), true); - assert_eq!(result[1].as_bool().unwrap(), true); - assert_eq!(result[2].as_bool().unwrap(), false); + let result: Vec = client.smismember("foo", vec![1, 2, 7]).await?; + assert_eq!(result[0], true); + assert_eq!(result[1], true); + assert_eq!(result[2], false); - let result = client.sismember("foo", 7).await?; - assert_eq!(result.as_bool().unwrap(), false); + let result: bool = client.sismember("foo", 7).await?; + assert_eq!(result, false); Ok(()) } @@ -152,10 +141,10 @@ pub async fn should_check_smismember(client: RedisClient, _: RedisConfig) -> Res pub async fn should_read_smembers(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let _ = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; - let result = client.smembers("foo").await?; + let _: () = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; + let result: HashSet = client.smembers("foo").await?; assert!(sets_eq( - &result.into_set().unwrap(), + &result, &vec_to_set(vec![ "1".into(), "2".into(), @@ -173,26 +162,23 @@ pub async fn should_smove_elements(client: RedisClient, _: RedisConfig) -> Resul check_null!(client, "foo{1}"); check_null!(client, "bar{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", 5).await?; + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", 5).await?; - let result = client.smove("foo{1}", "bar{1}", 7).await?; - assert_eq!(result.as_i64().unwrap(), 0); - let result = client.smove("foo{1}", "bar{1}", 5).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.smove("foo{1}", "bar{1}", 1).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.smove("foo{1}", "bar{1}", 7).await?; + assert_eq!(result, 0); + let result: i64 = client.smove("foo{1}", "bar{1}", 5).await?; + assert_eq!(result, 1); + let result: i64 = client.smove("foo{1}", "bar{1}", 1).await?; + assert_eq!(result, 1); - let foo = client.smembers("foo{1}").await?; - let bar = client.smembers("bar{1}").await?; + let foo: HashSet = client.smembers("foo{1}").await?; + let bar: HashSet = client.smembers("bar{1}").await?; assert!(sets_eq( - &foo.into_set().unwrap(), + &foo, &vec_to_set(vec!["2".into(), "3".into(), "4".into(), "6".into()]) )); - assert!(sets_eq( - &bar.into_set().unwrap(), - &vec_to_set(vec!["5".into(), "1".into()]) - )); + assert!(sets_eq(&bar, &vec_to_set(vec!["5".into(), "1".into()]))); Ok(()) } @@ -201,13 +187,13 @@ pub async fn should_spop_elements(client: RedisClient, _: RedisConfig) -> Result check_null!(client, "foo"); let expected = vec_to_set(vec!["1".into(), "2".into(), "3".into()]); - let _ = client.sadd("foo", vec![1, 2, 3]).await?; + let _: () = client.sadd("foo", vec![1, 2, 3]).await?; let result = client.spop("foo", None).await?; assert!(expected.contains(&result)); - let result = client.spop("foo", Some(3)).await?; - for value in result.into_array() { + let result: Vec = client.spop("foo", Some(3)).await?; + for value in result.into_iter() { assert!(expected.contains(&value)); } @@ -218,12 +204,12 @@ pub async fn should_get_random_member(client: RedisClient, _: RedisConfig) -> Re check_null!(client, "foo"); let expected = vec_to_set(vec!["1".into(), "2".into(), "3".into()]); - let _ = client.sadd("foo", vec![1, 2, 3]).await?; + let _: () = client.sadd("foo", vec![1, 2, 3]).await?; let result = client.srandmember("foo", None).await?; assert!(expected.contains(&result)); - let result = client.srandmember("foo", Some(3)).await?; - for value in result.into_array() { + let result: Vec = client.srandmember("foo", Some(3)).await?; + for value in result.into_iter() { assert!(expected.contains(&value)); } @@ -233,20 +219,17 @@ pub async fn should_get_random_member(client: RedisClient, _: RedisConfig) -> Re pub async fn should_remove_elements(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.srem("foo", 1).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.srem("foo", 1).await?; + assert_eq!(result, 0); - let _ = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; - let result = client.srem("foo", 1).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.srem("foo", vec![2, 3, 4, 7]).await?; - assert_eq!(result.as_i64().unwrap(), 3); + let _: () = client.sadd("foo", vec![1, 2, 3, 4, 5, 6]).await?; + let result: i64 = client.srem("foo", 1).await?; + assert_eq!(result, 1); + let result: i64 = client.srem("foo", vec![2, 3, 4, 7]).await?; + assert_eq!(result, 3); - let result = client.smembers("foo").await?; - assert!(sets_eq( - &result.into_set().unwrap(), - &vec_to_set(vec!["5".into(), "6".into()]) - )); + let result: HashSet = client.smembers("foo").await?; + assert!(sets_eq(&result, &vec_to_set(vec!["5".into(), "6".into()]))); Ok(()) } @@ -255,12 +238,12 @@ pub async fn should_sunion_elements(client: RedisClient, _: RedisConfig) -> Resu check_null!(client, "foo{1}"); check_null!(client, "bar{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sunion(vec!["foo{1}", "bar{1}"]).await?; + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: HashSet = client.sunion(vec!["foo{1}", "bar{1}"]).await?; assert!(sets_eq( - &result.into_set().unwrap(), + &result, &vec_to_set(vec![ "1".into(), "2".into(), @@ -281,14 +264,14 @@ pub async fn should_sunionstore_elements(client: RedisClient, _: RedisConfig) -> check_null!(client, "bar{1}"); check_null!(client, "baz{1}"); - let _ = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; - let _ = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; - let result = client.sunionstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - assert_eq!(result.as_i64().unwrap(), 8); - let result = client.smembers("baz{1}").await?; + let _: () = client.sadd("foo{1}", vec![1, 2, 3, 4, 5, 6]).await?; + let _: () = client.sadd("bar{1}", vec![3, 4, 5, 6, 7, 8]).await?; + let result: i64 = client.sunionstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + assert_eq!(result, 8); + let result: HashSet = client.smembers("baz{1}").await?; assert!(sets_eq( - &result.into_set().unwrap(), + &result, &vec_to_set(vec![ "1".into(), "2".into(), diff --git a/tests/integration/sorted_sets/mod.rs b/tests/integration/sorted_sets/mod.rs index 389adaad..78ecabdf 100644 --- a/tests/integration/sorted_sets/mod.rs +++ b/tests/integration/sorted_sets/mod.rs @@ -23,7 +23,7 @@ async fn create_lex_data(client: &RedisClient, key: &str) -> Result Result Result<(), }); for idx in 0..COUNT { - let result = publisher_client + let result: i64 = publisher_client .zadd("foo", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } let _ = jh.await?; @@ -81,10 +81,10 @@ pub async fn should_bzpopmax(client: RedisClient, _: RedisConfig) -> Result<(), for idx in 0..COUNT { sleep(Duration::from_millis(50)).await; - let result = publisher_client + let result: i64 = publisher_client .zadd("foo", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } let _ = jh.await?; @@ -94,23 +94,23 @@ pub async fn should_bzpopmax(client: RedisClient, _: RedisConfig) -> Result<(), pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client + let result: i64 = client .zadd("foo", None, None, false, false, vec![(0.0, 0), (1.0, 1)]) .await?; - assert_eq!(result.as_i64().unwrap(), 2); + assert_eq!(result, 2); for idx in 2..COUNT { - let value = client.zadd("foo", None, None, false, false, (idx as f64, idx)).await?; - assert_eq!(value.as_i64().unwrap(), 1); + let value: i64 = client.zadd("foo", None, None, false, false, (idx as f64, idx)).await?; + assert_eq!(value, 1); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, COUNT); - let result = client.zadd("foo", None, None, true, true, (0.1_f64, 0_i64)).await?; - assert!(approx_eq!(f64, result.as_f64().unwrap(), 0.1, ulps = 2)); + let result: f64 = client.zadd("foo", None, None, true, true, (0.1_f64, 0_i64)).await?; + assert!(approx_eq!(f64, result, 0.1, ulps = 2)); - let result = client + let result: i64 = client .zadd( "foo", Some(SetOptions::NX), @@ -120,8 +120,8 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( ((COUNT + 1) as f64, COUNT + 1), ) .await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client + assert_eq!(result, 1); + let result: i64 = client .zadd( "foo", Some(SetOptions::XX), @@ -131,9 +131,9 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( ((COUNT + 2) as f64, COUNT + 2), ) .await?; - assert_eq!(result.as_i64().unwrap(), 0); + assert_eq!(result, 0); - let result = client + let result: i64 = client .zadd( "foo", None, @@ -143,8 +143,8 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( (COUNT as f64, COUNT + 1), ) .await?; - assert_eq!(result.as_i64().unwrap(), 0); - let result = client + assert_eq!(result, 0); + let result: i64 = client .zadd( "foo", None, @@ -154,8 +154,8 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( ((COUNT + 2) as f64, COUNT + 1), ) .await?; - assert_eq!(result.as_i64().unwrap(), 0); - let result = client + assert_eq!(result, 0); + let result: i64 = client .zadd( "foo", None, @@ -165,8 +165,8 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( ((COUNT + 2) as f64, COUNT + 1), ) .await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client + assert_eq!(result, 1); + let result: i64 = client .zadd( "foo", None, @@ -176,7 +176,7 @@ pub async fn should_zadd_values(client: RedisClient, _: RedisConfig) -> Result<( ((COUNT + 1) as f64, COUNT + 1), ) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); Ok(()) } @@ -187,14 +187,14 @@ pub async fn should_zcard_values(client: RedisClient, _: RedisConfig) -> Result< for idx in 0..COUNT { let values = vec![(idx as f64, idx), ((idx + COUNT) as f64, idx + COUNT)]; - let result = client.zadd("foo", None, None, false, false, values).await?; - assert_eq!(result.as_i64().unwrap(), 2); + let result: i64 = client.zadd("foo", None, None, false, false, values).await?; + assert_eq!(result, 2); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT * 2); - let result = client.zcard("bar").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, COUNT * 2); + let result: i64 = client.zcard("bar").await?; + assert_eq!(result, 0); Ok(()) } @@ -202,16 +202,16 @@ pub async fn should_zcard_values(client: RedisClient, _: RedisConfig) -> Result< pub async fn should_zcount_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { let values = vec![(idx as f64, idx), ((idx + COUNT) as f64, idx + COUNT)]; - let result = client.zadd("foo", None, None, false, false, values).await?; - assert_eq!(result.as_i64().unwrap(), 2); + let result: i64 = client.zadd("foo", None, None, false, false, values).await?; + assert_eq!(result, 2); } - let result = client.zcount("foo", 0.0, (COUNT * 2) as f64).await?; - assert_eq!(result.as_i64().unwrap(), COUNT * 2); - let result = client.zcount("foo", 0.0, COUNT as f64 - 0.1).await?; - assert_eq!(result.as_i64().unwrap(), COUNT); - let result = client.zcount("foo", -1.0, -0.1).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zcount("foo", 0.0, (COUNT * 2) as f64).await?; + assert_eq!(result, COUNT * 2); + let result: i64 = client.zcount("foo", 0.0, COUNT as f64 - 0.1).await?; + assert_eq!(result, COUNT); + let result: i64 = client.zcount("foo", -1.0, -0.1).await?; + assert_eq!(result, 0); Ok(()) } @@ -223,17 +223,17 @@ pub async fn should_zdiff_values(client: RedisClient, _: RedisConfig) -> Result< let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } - let result = client.zdiff(vec!["foo{1}", "bar{1}"], false).await?; + let result: Vec = client.zdiff(vec!["foo{1}", "bar{1}"], false).await?; let _expected: Vec = expected.iter().map(|(_, v)| v.clone()).collect(); - assert_eq!(result.into_array(), _expected); + assert_eq!(result, _expected); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -243,7 +243,7 @@ pub async fn should_zdiff_values(client: RedisClient, _: RedisConfig) -> Result< expected[0..expected.len() - 1].to_vec(), ) .await?; - let result = client.zdiff(vec!["foo{1}", "bar{1}"], true).await?; + let result: RedisValue = client.zdiff(vec!["foo{1}", "bar{1}"], true).await?; let expected: Vec<(RedisValue, f64)> = expected.into_iter().map(|(s, v)| (v, s)).collect(); assert_eq!( result.into_zset_result().unwrap(), @@ -261,16 +261,16 @@ pub async fn should_zdiffstore_values(client: RedisClient, _: RedisConfig) -> Re let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } - let result = client.zdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + let result: i64 = client.zdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + assert_eq!(result, COUNT); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -280,8 +280,8 @@ pub async fn should_zdiffstore_values(client: RedisClient, _: RedisConfig) -> Re expected[0..expected.len() - 1].to_vec(), ) .await?; - let result = client.zdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.zdiffstore("baz{1}", vec!["foo{1}", "bar{1}"]).await?; + assert_eq!(result, 1); Ok(()) } @@ -289,12 +289,12 @@ pub async fn should_zdiffstore_values(client: RedisClient, _: RedisConfig) -> Re pub async fn should_zincrby_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { check_null!(client, "foo"); - let result = client.zincrby("foo", 1.0, "a").await?; - assert_eq!(result.as_f64().unwrap(), 1.0); - let result = client.zincrby("foo", 2.5, "a").await?; - assert_eq!(result.as_f64().unwrap(), 3.5); - let result = client.zincrby("foo", 1.2, "b").await?; - assert_eq!(result.as_f64().unwrap(), 1.2); + let result: f64 = client.zincrby("foo", 1.0, "a").await?; + assert_eq!(result, 1.0); + let result: f64 = client.zincrby("foo", 2.5, "a").await?; + assert_eq!(result, 3.5); + let result: f64 = client.zincrby("foo", 1.2, "b").await?; + assert_eq!(result, 1.2); Ok(()) } @@ -306,16 +306,16 @@ pub async fn should_zinter_values(client: RedisClient, _: RedisConfig) -> Result let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } - let result = client.zinter(vec!["foo{1}", "bar{1}"], None, None, false).await?; - assert_eq!(result.into_array(), Vec::new()); + let result: Vec = client.zinter(vec!["foo{1}", "bar{1}"], None, None, false).await?; + assert!(result.is_empty()); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -325,7 +325,7 @@ pub async fn should_zinter_values(client: RedisClient, _: RedisConfig) -> Result expected[0..expected.len() - 1].to_vec(), ) .await?; - let result = client.zinter(vec!["foo{1}", "bar{1}"], None, None, true).await?; + let result: RedisValue = client.zinter(vec!["foo{1}", "bar{1}"], None, None, true).await?; // scores are added together with a weight of 1 in this example let mut expected: Vec<(RedisValue, f64)> = expected.into_iter().map(|(s, v)| (v, s * 2.0)).collect(); // zinter returns results in descending order based on score @@ -343,18 +343,18 @@ pub async fn should_zinterstore_values(client: RedisClient, _: RedisConfig) -> R let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } - let result = client + let result: i64 = client .zinterstore("baz{1}", vec!["foo{1}", "bar{1}"], None, None) .await?; - assert_eq!(result.as_i64().unwrap(), 0); + assert_eq!(result, 0); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -364,10 +364,10 @@ pub async fn should_zinterstore_values(client: RedisClient, _: RedisConfig) -> R expected[0..expected.len() - 1].to_vec(), ) .await?; - let result = client + let result: i64 = client .zinterstore("baz{1}", vec!["foo{1}", "bar{1}"], None, None) .await?; - assert_eq!(result.as_i64().unwrap(), COUNT - 1); + assert_eq!(result, COUNT - 1); Ok(()) } @@ -376,12 +376,12 @@ pub async fn should_zlexcount(client: RedisClient, _: RedisConfig) -> Result<(), check_null!(client, "foo"); let _ = create_lex_data(&client, "foo").await?; - let result = client.zlexcount("foo", "-", "+").await?; - assert_eq!(result.as_i64().unwrap(), 26); - let result = client.zlexcount("foo", "a", "b").await?; - assert_eq!(result.as_i64().unwrap(), 2); - let result = client.zlexcount("foo", "a", "(b").await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.zlexcount("foo", "-", "+").await?; + assert_eq!(result, 26); + let result: i64 = client.zlexcount("foo", "a", "b").await?; + assert_eq!(result, 2); + let result: i64 = client.zlexcount("foo", "a", "(b").await?; + assert_eq!(result, 1); Ok(()) } @@ -390,13 +390,13 @@ pub async fn should_zpopmax(client: RedisClient, _: RedisConfig) -> Result<(), R let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.zpopmax("foo", None).await?; + let result: RedisValue = client.zpopmax("foo", None).await?; let (member, score) = result.into_zset_result().unwrap().pop().unwrap(); assert_eq!(score, (COUNT - idx - 1) as f64); assert_eq!(member, (COUNT - idx - 1).to_string().into()); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } @@ -405,13 +405,13 @@ pub async fn should_zpopmin(client: RedisClient, _: RedisConfig) -> Result<(), R let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.zpopmin("foo", None).await?; + let result: RedisValue = client.zpopmin("foo", None).await?; let (member, score) = result.into_zset_result().unwrap().pop().unwrap(); assert_eq!(score, idx as f64); assert_eq!(member, idx.to_string().into()); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } @@ -420,13 +420,13 @@ pub async fn should_zrandmember(client: RedisClient, _: RedisConfig) -> Result<( let _ = create_count_data(&client, "foo").await?; for _ in 0..COUNT * 2 { - let result = client.zrandmember("foo", Some((1, true))).await?; + let result: RedisValue = client.zrandmember("foo", Some((1, true))).await?; let (member, score) = result.into_zset_result().unwrap().pop().unwrap(); assert!(score >= 0.0 && score < COUNT as f64); assert_eq!(member.into_string().unwrap(), score.to_string()); } - let result = client.zrandmember("foo", Some((COUNT, true))).await?; + let result: RedisValue = client.zrandmember("foo", Some((COUNT, true))).await?; let result = result.into_zset_result().unwrap(); for (member, score) in result.into_iter() { assert!(score >= 0.0 && score < COUNT as f64); @@ -441,12 +441,12 @@ pub async fn should_zrangestore_values(client: RedisClient, _: RedisConfig) -> R check_null!(client, "bar{1}"); let _ = create_count_data(&client, "foo{1}").await?; - let result = client + let result: i64 = client .zrangestore("bar{1}", "foo{1}", 0, COUNT, None, false, None) .await?; - assert_eq!(result.as_i64().unwrap(), COUNT); - let result = client.zcard("bar{1}").await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + assert_eq!(result, COUNT); + let result: i64 = client.zcard("bar{1}").await?; + assert_eq!(result, COUNT); Ok(()) } @@ -591,12 +591,12 @@ pub async fn should_zrank_values(client: RedisClient, _: RedisConfig) -> Result< let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.zrank("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), idx); + let result: i64 = client.zrank("foo", idx).await?; + assert_eq!(result, idx); } - let result = client.zrank("foo", COUNT + 1).await?; - assert!(result.is_null()); + let result: Option = client.zrank("foo", COUNT + 1).await?; + assert!(result.is_none()); Ok(()) } @@ -604,77 +604,77 @@ pub async fn should_zrank_values(client: RedisClient, _: RedisConfig) -> Result< pub async fn should_zrem_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let _ = create_count_data(&client, "foo").await?; - let result = client.zrem("foo", COUNT + 1).await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zrem("foo", COUNT + 1).await?; + assert_eq!(result, 0); for idx in 0..COUNT { - let result = client.zrem("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), 1); - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), COUNT - (idx + 1)); + let result: i64 = client.zrem("foo", idx).await?; + assert_eq!(result, 1); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, COUNT - (idx + 1)); } - let result = client.zrem("foo", 0).await?; - assert_eq!(result.as_i64().unwrap(), 0); - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: i64 = client.zrem("foo", 0).await?; + assert_eq!(result, 0); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } pub async fn should_zremrangebylex(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let expected = create_lex_data(&client, "foo").await?; - let result = client.zremrangebylex("foo", "-", "+").await?; - assert_eq!(result.as_usize().unwrap(), expected.len()); - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: usize = client.zremrangebylex("foo", "-", "+").await?; + assert_eq!(result, expected.len()); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); let _ = create_lex_data(&client, "foo").await?; for (_, value) in expected.iter() { let value_str = value.as_str().unwrap().to_string(); - let result = client.zremrangebylex("foo", &value_str, &value_str).await?; - assert_eq!(result.as_i64().unwrap(), 1); + let result: i64 = client.zremrangebylex("foo", &value_str, &value_str).await?; + assert_eq!(result, 1); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } pub async fn should_zremrangebyrank(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let expected = create_count_data(&client, "foo").await?; - let result = client.zremrangebyrank("foo", 0, COUNT).await?; - assert_eq!(result.as_usize().unwrap(), expected.len()); - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: usize = client.zremrangebyrank("foo", 0, COUNT).await?; + assert_eq!(result, expected.len()); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); let _ = create_count_data(&client, "foo").await?; for _ in 0..COUNT { // this modifies the set so the idx cant change - let result = client.zremrangebyrank("foo", 0, 0).await?; - assert_eq!(result.as_usize().unwrap(), 1); + let result: usize = client.zremrangebyrank("foo", 0, 0).await?; + assert_eq!(result, 1); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } pub async fn should_zremrangebyscore(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let expected = create_count_data(&client, "foo").await?; - let result = client.zremrangebyscore("foo", 0 as f64, COUNT as f64).await?; - assert_eq!(result.as_usize().unwrap(), expected.len()); - let result = client.zcard("foo").await?; - assert_eq!(result.as_i64().unwrap(), 0); + let result: usize = client.zremrangebyscore("foo", 0 as f64, COUNT as f64).await?; + assert_eq!(result, expected.len()); + let result: i64 = client.zcard("foo").await?; + assert_eq!(result, 0); let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.zremrangebyscore("foo", idx as f64, idx as f64).await?; - assert_eq!(result.as_usize().unwrap(), 1); + let result: usize = client.zremrangebyscore("foo", idx as f64, idx as f64).await?; + assert_eq!(result, 1); } - let result = client.zcard("foo").await?; - assert_eq!(result.as_usize().unwrap(), 0); + let result: usize = client.zcard("foo").await?; + assert_eq!(result, 0); Ok(()) } @@ -682,12 +682,12 @@ pub async fn should_zremrangebyscore(client: RedisClient, _: RedisConfig) -> Res pub async fn should_zrevrank_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { let _ = create_count_data(&client, "foo").await?; - let result = client.zrevrank("foo", COUNT + 1).await?; - assert!(result.is_null()); + let result: Option = client.zrevrank("foo", COUNT + 1).await?; + assert!(result.is_none()); for idx in 0..COUNT { - let result = client.zrevrank("foo", idx).await?; - assert_eq!(result.as_i64().unwrap(), COUNT - (idx + 1)); + let result: i64 = client.zrevrank("foo", idx).await?; + assert_eq!(result, COUNT - (idx + 1)); } Ok(()) @@ -697,12 +697,12 @@ pub async fn should_zscore_values(client: RedisClient, _: RedisConfig) -> Result let _ = create_count_data(&client, "foo").await?; for idx in 0..COUNT { - let result = client.zscore("foo", idx).await?; - assert_eq!(result.as_f64().unwrap(), idx as f64); + let result: f64 = client.zscore("foo", idx).await?; + assert_eq!(result, idx as f64); } - let result = client.zscore("foo", COUNT + 1).await?; - assert!(result.is_null()); + let result: Option = client.zscore("foo", COUNT + 1).await?; + assert!(result.is_none()); Ok(()) } @@ -714,17 +714,17 @@ pub async fn should_zunion_values(client: RedisClient, _: RedisConfig) -> Result let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } let result = client.zunion(vec!["foo{1}", "bar{1}"], None, None, false).await?; let _expected: Vec = expected.iter().map(|(_, v)| v.clone()).collect(); assert_eq!(result.into_array(), _expected); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -759,18 +759,18 @@ pub async fn should_zunionstore_values(client: RedisClient, _: RedisConfig) -> R let mut expected: Vec<(f64, RedisValue)> = Vec::with_capacity(COUNT as usize); for idx in 0..COUNT { expected.push((idx as f64, idx.to_string().into())); - let result = client + let result: i64 = client .zadd("foo{1}", None, None, false, false, (idx as f64, idx)) .await?; - assert_eq!(result.as_i64().unwrap(), 1); + assert_eq!(result, 1); } - let result = client + let result: i64 = client .zunionstore("baz{1}", vec!["foo{1}", "bar{1}"], None, None) .await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + assert_eq!(result, COUNT); - let _ = client + let _: () = client .zadd( "bar{1}", None, @@ -780,23 +780,23 @@ pub async fn should_zunionstore_values(client: RedisClient, _: RedisConfig) -> R expected[0..expected.len() - 1].to_vec(), ) .await?; - let result = client + let result: i64 = client .zunionstore("baz{1}", vec!["foo{1}", "bar{1}"], None, None) .await?; - assert_eq!(result.as_i64().unwrap(), COUNT); + assert_eq!(result, COUNT); Ok(()) } pub async fn should_zmscore_values(client: RedisClient, _: RedisConfig) -> Result<(), RedisError> { for idx in 0..COUNT { - let _ = client.zadd("foo", None, None, false, false, (idx as f64, idx)).await?; + let _: () = client.zadd("foo", None, None, false, false, (idx as f64, idx)).await?; } - let result = client.zmscore("foo", vec![0, 1]).await?; - assert_eq!(result.into_array(), vec!["0".into(), "1".into()]); - let result = client.zmscore("foo", vec![11]).await?; - assert!(result.is_null()); + let result: Vec = client.zmscore("foo", vec![0, 1]).await?; + assert_eq!(result, vec!["0".into(), "1".into()]); + let result: Option = client.zmscore("foo", vec![11]).await?; + assert!(result.is_none()); Ok(()) } diff --git a/tests/integration/utils.rs b/tests/integration/utils.rs index 24213a99..368007a5 100644 --- a/tests/integration/utils.rs +++ b/tests/integration/utils.rs @@ -1,3 +1,5 @@ +#![allow(unused_macros)] + use crate::chaos_monkey::set_test_kind; use fred::client::RedisClient; use fred::error::RedisError; @@ -43,7 +45,7 @@ where let _jh = client.connect(Some(policy)); let _ = client.wait_for_connect().await.expect("Failed to connect client"); - let _ = client.flushall_cluster().await; + let _: () = client.flushall_cluster().await.expect("Failed to flushall"); func(_client, config.clone()).await.expect("Failed to run test"); let _ = client.quit().await; } @@ -68,7 +70,7 @@ where let _jh = client.connect(Some(policy)); let _ = client.wait_for_connect().await.expect("Failed to connect client"); - let _ = client.flushall(false).await; + let _: () = client.flushall(false).await.expect("Failed to flushall"); func(_client, config.clone()).await.expect("Failed to run test"); let _ = client.quit().await; } @@ -158,9 +160,10 @@ macro_rules! return_err( ); macro_rules! check_null( - ($client:ident, $arg:expr) => { - if !$client.get($arg).await?.is_null() { + ($client:ident, $arg:expr) => { { + let foo: RedisValue = $client.get($arg).await?; + if !foo.is_null() { panic!("expected {} to be null", $arg); } - } + } } );