RustのRedisで色々な型を受けてみた

# 目的
RustのRedisクレートはいい感じに型変換をしてくれます。ただし最近導入されたストリーム型は面倒な形をしているので注意が必要です。

# プログラム
## 簡単な例
queryメソッドの戻り値をbindする型で変換してくれます。

```rust:Cargo.toml
[package]
name = "redis_test"
version = "0.1.0"
edition = "2018"

[dependencies]
r2d2_redis = "^0.12"
```
```rust:main.rs
use std::error::Error;
use std::ops::DerefMut;

type RedisConn = r2d2_redis::r2d2::PooledConnection<r2d2_redis::RedisConnectionManager>;

fn get_conn() -> Result<RedisConn, Box<dyn Error>>{
    let manager = r2d2_redis::RedisConnectionManager::new("redis://localhost:6379")?;
    let pool = r2d2_redis::r2d2::Pool::builder().max_size(2).build(manager)?;
    Ok(pool.get()?)
}

fn main() -> Result<(), Box<dyn Error>>{
    let mut conn = get_conn()?;
    r2d2_redis::redis::cmd("SET").arg("aaa").arg("1").query(conn.deref_mut())?;
    let res: String = r2d2_redis::redis::cmd("GET").arg("aaa").query(conn.deref_mut())?;
    println!("{:?}", res);
    let res: i64 = r2d2_redis::redis::cmd("GET").arg("aaa").query(conn.deref_mut())?;
    println!("{:?}", res);
}
```
```text:結果
"1"
1
```

## pipe
パイプを使うことで複数の値を取得することができます。

```rust:main.rs
fn main() -> Result<(), Box<dyn Error>>{
    let mut conn = get_conn()?;
    r2d2_redis::redis::pipe()
        .cmd("DEL").arg("aaa")
        .cmd("SET").arg("aaa").arg("1")
        .cmd("DEL").arg("bbb")
        .cmd("SET").arg("bbb").arg("2")
        .query(conn.deref_mut())?;
    let res: (String, i64) =  r2d2_redis::redis::pipe()
        .cmd("GET").arg("aaa")
        .cmd("GET").arg("bbb")
        .query(conn.deref_mut())?;
    println!("{:?}", res);
}
```
```text:結果
("1", 1)
```
## List
配列を回して引数を追加することもできます。

```rust:main.rs
fn main() -> Result<(), Box<dyn Error>>{
    let mut conn = get_conn()?;
    let args = vec![1,2,3];
    let mut pipe = r2d2_redis::redis::pipe();
    let cmd = pipe
        .cmd("DEL").arg("aaa")
        .cmd("RPUSH").arg("aaa");
    for i in args.iter() {
        cmd.arg(*i);
    }
    cmd.query(conn.deref_mut())?;
    let list: Vec<i64> = r2d2_redis::redis::cmd("LRANGE")
        .arg("aaa").arg(0).arg(-1).query(conn.deref_mut())?;
    println!("{:?}", list);
}
```
```text:結果
[1, 2, 3]
```

## Hash
HashMapに変換することができます。

```rust:main.rs
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn Error>>{
    let mut conn = get_conn()?;
    r2d2_redis::redis::pipe()
        .cmd("DEL").arg("aaa")
        .cmd("HSET").arg("aaa").arg("a").arg("1")
        .cmd("HSET").arg("aaa").arg("b").arg("2")
        .query(conn.deref_mut())?;
    let res: HashMap<String, String> = r2d2_redis::redis::cmd("HGETALL")
        .arg("aaa").query(conn.deref_mut())?;
    println!("{:?}", res);
}
```
```text:結果
{"a": "1", "b": "2"}
```

## Stream
Vecが重複しているように見えますが、こうしないと正しく取得できませんでした。

```rust:main.rs
fn main() -> Result<(), Box<dyn Error>>{
    let mut conn = get_conn()?;
    r2d2_redis::redis::pipe()
        .cmd("DEL").arg("aaa")
        .cmd("DEL").arg("bbb")
        .cmd("XADD").arg("aaa").arg("*").arg("a").arg("1").arg("b").arg("2")
        .cmd("XADD").arg("bbb").arg("*").arg("c").arg("1").arg("d").arg("2")
        .cmd("XADD").arg("aaa").arg("*").arg("a").arg("3").arg("b").arg("4")
        .cmd("XADD").arg("bbb").arg("*").arg("c").arg("3").arg("d").arg("4")
        .query(conn.deref_mut())?;
    let res: Vec<Vec<(String, Vec<Vec<(String, HashMap<String, String>)>>)>> = r2d2_redis::redis::cmd("XREAD")
        .arg("COUNT").arg("2").arg("STREAMS").arg("aaa").arg("bbb").arg("0").arg("0").query(conn.deref_mut())?;
    println!("{:?}", res);
}
```
```text:結果
[
    [("aaa", [[("1574640845410-0", {"a": "1", "b": "2"})], [("1574640845410-1", {"a": "3", "b": "4"})]])], 
    [("bbb", [[("1574640845410-0", {"d": "2", "c": "1"})], [("1574640845410-1", {"c": "3", "d": "4"})]])]
]
```