Rust の型変換イディオム

# Rust の型変換イディオム

この記事は [Rustその2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/rust2) の 12 日目の記事です。


## `Option<String>` to `Option<&str>`

```rust
let a: Option<String> = Some("0".to_string());
let b: Option<&str> = a.as_deref();
// または let b: Option<&str> = a.as_ref().map(AsRef::as_ref);
```

## `Option<Vec<T>> -> Option<&[T]>`

```rust
let a: Option<Vec<u8>> = Some(vec![0]);
let b: Option<&[u8]> = a.as_deref();
```

## `Option<Rc<T>> -> Option<&T>`, `Option<Arc<T>> -> Option<&T>`

`Option::as_deref` は Option の中の型が Deref トレイトを実装しているときに Deref::Target の参照へ変換できる

```rust
use std::rc::Rc;
let a: Option<Rc<u8>> = Some(Rc::new(0));
let b: Option<&u8> = a.as_deref();
```

## `Option<String>` to `&Option<&str>`

* https://stackoverflow.com/questions/31233938/converting-from-optionstring-to-optionstr

```rust
let a: Option<String> = Some("0".to_string());
let b: Option<&str> = a.as_ref().map(AsRef::as_ref);
let c: &Option<&str> = &b;
```

## `Vec<String>` to `&[&str]`

```rust
let a: Vec<String> = vec!["0".to_string()];
let b: Vec<&str> = a.iter().map(AsRef::as_ref).collect();
let c: &[&str] = b.as_ref();
```

## `Option<Vec<String>>` -> `&Option<&[&str]>`

```rust
let a: Option<Vec<String>> = Some(vec!["0".to_string()]);
let b: Option<&[String]> = a.as_ref().map(AsRef::as_ref);
let c: Option<Vec<&str>> = b.map(|lst| lst.iter().map(|s| s.as_ref()).collect::<Vec<_>>());
let d: Option<&[&str]> = c.as_ref().map(|lst| lst.as_ref());
```

```rust
let a: Option<String> = Some("0".to_owned());
let b: Option<&String> = a.as_ref();
let c: Option<&str> = b.map(|x| &**x);
let d: &Option<&str> = &c; //   ||||
                                |||+ x: &String
                                ||+ *x: String
                                |+ **x: str:  (*<String as Deref<Target = str>>::deref(*x))
                                + &**x: &str 
```

## `Option<T>` to `Option<&T>`

```rust
let a: Option<i32> = Some(0);
let b: Option<&i32> = a.as_ref();
```

## `Result<T, E>` to `Result<&T, &E>`

```rust
let a: Result<i32, ()> = Ok(0);
let b: Result<&i32, &()> = a.as_ref();
```

## `String` -> `&str`

```rust
let a: String = "0".to_string();
let b: &str = &a.to_string()[..];
```

```rust
let a: String = "0".to_string();
let b: &str = &*a;
```

## `&str` -> `&str` (文字列の先頭一致したいとき)

str に対して n 文字一致をしたいとき

```rust
let hoge = "hoge-huga".to_string();
match hoge.chars().take(5).collect::<String>().as_ref() {
    "hoge-" => { println!("hoge"); }
    "huga-" => { println!("huga"); }
    _ => { println!("err") }
}
```

- [str::get_unchecked](https://doc.rust-lang.org/std/primitive.str.html#method.get_unchecked) を使いたいところだけど ascii 以外の文字列の場合、スライスの境界チェックができず unsafe 


## `Result<T, E>` -> `Option<T>`

```rust
let a: Result<i32, ()> = Ok(0);
let b: Option<i32> = a.ok();
```

## `Result<T, E>` -> `Option<E>`

```rust
let a: Result<i32, ()> = Ok(0);
let b: Option<()> = a.err();
```

## `Option<T>` -> `Result<T, E>`

```rust
let a: Option<i32> = Some(0);
let b: Result<i32, ()> = a.ok_or(());
```

```rust
let a: Option<i32> = Some(0);
let b: Result<i32, ()> = a.ok_or_else(|| ());
```

## `Option<T>` -> `Vec<T>`

```rust
let a: Option<i32> = Some(0);
let b: Vec<i32> = a.into_iter().collect::<Vec<_>>();
```

## `Option<T>` -> `Vec<&T>`

```rust
let a: Option<i32> = Some(0);
let b: Vec<&i32> = a.iter().collect::<Vec<_>>();
```

## `Vec<T>` -> `Option<T>`

```rust
let a: Vec<i32> = vec![0];
let b: Option<i32> = a.into_iter().next();
```

## `Vec<T>` -> `Option<&T>`

```rust
let a: Vec<i32> = vec![0];
let b: Option<i32> = a.first();
```

## `Option<Option<T>>` -> `Option<T>`

```rust
let a: Option<Option<i32>> = Some(Some(0));
let b: Option<i32> = a.and_then(|opt| opt);
```

## `Result<Option<T>, E>` -> `Option<Result<T, E>>`

```rust
let a: Result<Option<i32>, ()> = Ok(Some(0));
let b: Option<Result<i32, ()>> = match a {
    Ok(Some(x)) => Some(Ok(x)),
    Ok(None) => None,
    Err(e) => Some(Err(e)),
};
```

## `Option<Result<T, E>>` -> `Result<Option<T>, E>`

```rust
let a: Option<Result<i32, ()>> = Some(Ok(0));
let b: Result<Option<i32>, ()> = match self {
    Some(Ok(x)) => Ok(Some(x)),
    Some(Err(e)) => Err(e),
    None => Ok(None),
};
```

## `Vec<Result<T, E>>` -> `Result<Vec<T>, E>`

```rust
let a: Vec<Result<i32, ()>> = vec![Ok(0), Err(())];
let b: Result<Vec<i32>, ()> = a.into_iter().collect();
assert_eq!(b, Err(()));
```

## `Vec<Option<T>>` -> `Option<Vec<T>>`

```rust
let a: Vec<Option<i32>> = vec![Some(0), None];
let b: Option<Vec<i32>> = a.into_iter().collect();
assert_eq!(b, None);
```

## `&T -> &[T]` (Tの参照から要素1のTのスライスの参照への変換)

```rust
let a: u32 = 0;
let a_slice: &[u32] = std::slice::from_ref(&a);
```

## `&str` -> `&[u8]`

```rust
let a: &str = "0";
let b: &[u8] = a.as_bytes();
```

## `String` -> `Vec<u8>`

```rust
let a: String = "0".to_string();
let b: Vec<u8> = a.into_bytes();
```

## `String` -> `Box<str>`, `Rc<str>`, `Arc<str>`

```rust
use std::rc::Rc;
use std::sync::Arc;

let a = String::from("a");

let s: Box<str> = Box::from(a.clone());
let s: Rc<str> = Rc::from(a.clone());
let s: Arc<str> = Arc::from(a.clone());
```

- https://mmi.hatenablog.com/entry/2019/02/14/233522

## `[u8]` -> `Box<[u8]>`, `Rc<[u8]>`, `Arc<[u8]>`

```rust
use std::rc::Rc;
use std::sync::Arc;

let s: Box<[u8]> = Box::from([1,2,3]);
let s: Rc<[u8]> = Rc::from([1,2,3]);
let s: Arc<[u8]> = Arc::from([1,2,3]);
```

- https://mmi.hatenablog.com/entry/2019/02/14/233522

## `Vec<u8>` -> `Box<[u8]>`, `Rc<[u8]>`, `Arc<[u8]>`

```rust
use std::rc::Rc;
use std::sync::Arc;

let s: Box<[u8]> = Box::from(vec![1,2,3]);
let s: Rc<[u8]> = Rc::from(vec![1,2,3]);
let s: Arc<[u8]> = Arc::from(vec![1,2,3]);
```

- https://mmi.hatenablog.com/entry/2019/02/14/233522

## `&[u8]` -> `&str`

```rust
let a: &[u8] = &[48];
let b: &str = std::str::from_utf8(a).unwrap();
assert_eq!("0", b);
```

## `&Bytes` -> `&str`

- https://docs.rs/bytes/1.1.0/bytes/struct.Bytes.html
- https://stackoverflow.com/questions/53841510/how-can-i-convert-a-bytesbytes-to-a-str-without-making-any-copies

```rust
let b = bytes::Bytes::from("hello");
std::str::from_utf8(&b).unwrap();
```

## `Vec<u8>` -> `String`

```rust
let a: Vec<u8> = vec![48];
let b: String = String::from_utf8(a).unwrap();
assert_eq!("0".to_string(), b);
```

## `String`, `&str` -> `u8`, `u16`, `u32` `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, `isize`, `f32`, `f64` （文字列から数値への変換）

```rust
let a: &str = "0";
let b: u8 = a.parse::<u8>().unwrap();

let a: String = "48".to_string();
let b: f64 = a.parse::<f64>().unwrap();
```

## `u8` -> `u16` -> `u32` -> `u64` （安全なアップキャスト）


安全なアップキャスト

```rust
let a: u8 = 0;
let b: u16 = From::from(a);
let c = u32::from(b); // こういう風にも書ける
let d: u64 = From::from(c);
```

## `u64` -> `u32` -> `u16` -> `u8` （安全なダウンキャスト）


```rust
let a: u64 = 255;
let b: u32 = TryFrom::try_from(a).unwrap();
let c: u16 = u16::try_from(b).unwrap(); // こうも書ける
let d: u8 = TryFrom::try_from(c).unwrap();
```

## `usize` , `isize` を含む signed と unsigned 間のキャスト

num crate の [`ToPrimitive`](https://docs.rs/num/latest/num/trait.ToPrimitive.html) と [`FromPrimitive`](https://docs.rs/num/latest/num/trait.FromPrimitive.html) を使います

```rust
use num::FromPrimitive;
let a: Option<u8> = u8::from_usize(1_usize);
let a: Option<u8> = u8::from_isize(1_isize);
let a: Option<i8> = i8::from_u8(1_u8);
let a: Option<i64> = i64::from_usize(1_usize);
```

- https://stackoverflow.com/questions/28273169/how-do-i-convert-between-numeric-types-safely-and-idiomatically

## 数値 -> `String` の桁ゼロ埋め (left-pad)

- https://stackoverflow.com/questions/50458144/what-is-the-easiest-way-to-pad-a-string-with-0-to-the-left

```rust
assert_eq!("00000110", format!("{:0>8}", "110"));
//                                |||
//                                ||+-- width
//                                |+--- align
//                                +---- fill
```

## `f64` -> `i64`

```rust
let a: f64 = 0.1;
let b: i64 = a.round() as i64;
```


## 任意の struct を `Vec<u8>` に変換

２通りある

### 対象の struct がすべて自分のクレートのとき => bincode + serde を使う

* https://github.com/servo/bincode

```rust
#[derive(Serialize, Default)]
struct MyStruct {
    id: u8,
    data: [u8; 1024],
}

fn main() {
    let my_struct = MyStruct::default();
    let bytes: Vec<u8> = bincode::serialize(&my_struct).unwrap();
}
```

### 対象の struct が別クレート or bindgen などで自動生成されていて、Sized(コンパイル時に大きさが決まっている) のとき => `std::slice::from_raw_parts` を使う

* https://stackoverflow.com/questions/28127165/how-to-convert-struct-to-u8

```rust
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
    std::slice::from_raw_parts(
        (p as *const T) as *const u8,
        std::mem::size_of::<T>(),
    )
}

#[derive(Default)]
struct MyStruct {
    id: u8,
    data: [u8; 1024],
}

fn main() {
    let my_struct = MyStruct::default();
    let bytes: &[u8] = unsafe { any_as_u8_slice(&my_struct) };
    println!("{:?}", bytes);
}
```

## `unixtimestamp(millis)` -> `DateTime<UTC>`

```rust
use chrono::offset::TimeZone;
let dt: Option<chrono::DateTime<Utc>> = chrono::Utc.timestamp_millis_opt(0).single();
```

* https://docs.rs/chrono/0.4.19/chrono/offset/trait.TimeZone.html?search=#method.timestamp_millis_opt
* https://qiita.com/fujitayy/items/ae6175118cbed7134594#unix-time%E3%81%8B%E3%82%89%E3%81%AE%E5%A4%89%E6%8F%9B

## `DateTime<UTC>` -> `unixtimestamp(millis)`

```rust
let timestamp: i64 = chrono::Utc::now().timestamp_millis();
```

* https://docs.rs/chrono/0.4.19/chrono/struct.DateTime.html#method.timestamp_millis
* https://qiita.com/fujitayy/items/ae6175118cbed7134594#unix-time%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B

## ISO8601(RFC3339) -> `DateTime<Utc>`

https://docs.rs/chrono/0.4.19/chrono/struct.DateTime.html#method.parse_from_rfc3339

```rs
let date = chrono::DateTime::parse_from_rfc3339("1970-01-01T00:00:00.000000000Z").unwrap().with_timezone(&chrono::Utc);
```

## `DateTime<Utc>` -> ISO8601(RFC3339) (millis)

https://docs.rs/chrono/0.4.19/chrono/struct.DateTime.html#method.to_rfc3339_opts

```rs
let date_str = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true); // 2018-01-26T18:30:09.453Z"
```

## `"{}"` -> `Option<DateTime<Utc>`

- https://qiita.com/legokichi/items/2a72ae89ef76f6252166 も参照のこと

```rust
use chrono::{Utc, DateTime};

#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct A {
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(with = "chrono::serde::ts_milliseconds_option")]
    #[serde(default)] // 存在しないフィールドの default は None にするという指定
    pub time: Option<DateTime<Utc>>,
}
#[test]
fn test_opt_unix_millis(){
    let json = r#"{"time": 0}"#;
    assert!(serde_json::from_str::<A>(json).unwrap().time.is_some());

    let json = r#"{"time": null}"#;
    assert!(serde_json::from_str::<A>(json).unwrap().time.is_none());

    let json = r#"{}"#;
    assert!(serde_json::from_str::<A>(json).unwrap().time.is_none());

    let obj = A{time: None};
    assert_eq!(serde_json::to_string(&obj).unwrap(), r#"{}"#);
    
    let obj = A{time: Some(DateTime::parse_from_rfc3339("1970-01-01T00:00:00.000000000Z").unwrap().with_timezone(&Utc))};
    assert_eq!(serde_json::to_string(&obj).unwrap(), r#"{"time":0}"#);
}
```



## `&'a str` -> `Box<dyn std::error::Error + Send + Sync + 'a>`

驚くべきことに [`std::boxed::Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) は

```rust
impl<'a, '_> From<&'_ str> for Box<dyn Error + Send + Sync + 'a>
```

を[実装している](https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-From%3C%26%27_%20str%3E-1)ので

```rust
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
    let a_boxed_error: Box<dyn std::error::Error + Send + Sync + '_> = "error!".into();
    Err(a_boxed_error)?;
    Ok(())
}
```

と書くことができる


* https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-From%3C%26%27_%20str%3E-1

## `String` -> `Box<dyn Error + Send + Sync + 'static>`

同上

```rust
let a_boxed_error: Box<dyn std::error::Error + Send + Sync + 'static> = Box::from("a".to_string());
```

## `impl std::error::Error` -> `std::io::Error + Send + Sync`

とりあえず `std::io::Error` がほしいときにつかう

```
let io_err = std::io::Error::new(std::io::ErrorKind::Other, err);
```

## Nullable かつ undefinedable なフィールドを含む JSON を シリアライズ | デシリアライズする

ts だと

```ts
interface Foo {
  a?: string | null;
}
```

json schema だと

```json
{
  "type": "object",
  "properties": {
    "a": { "type": ["string", "null"] }
  },
  "required": []
}
```

のような Nullable かつ undefinable な json があった場合、 __js_option を使うこと。__

https://crates.io/crates/js_option

### `#[serde(skip_serializing_if = "Option::is_none")]` を使った場合

serde の `skip_serializing_if` を使った場合、 シリアライズ時にはうまくいくが、デシリアライズ時に null と unefined の区別がつかない。

```rust
#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq)]
struct A {
    // nullable
    a: Option<i32>,

    // undefinable
    #[serde(skip_serializing_if = "Option::is_none")]
    b: Option<i32>,

    // nullable かつ undefinable
    #[serde(skip_serializing_if = "Option::is_none")]
    c: Option<Option<i32>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    d: Option<Option<i32>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    e: Option<Option<i32>>,

    // nullable
    f: Option<Option<i32>>,
    g: Option<Option<i32>>,
    h: Option<Option<i32>>,
    
}

fn main() {
    let original = A{
        // nullable
        a:None,
        // undefinable
        b:None,
        // nullable かつ undefinable
        c: None, d: Some(None), e: Some(Some(0)),
        // nullable
        f: None, g: Some(None), h: Some(Some(0))
    };
    let json = serde_json::to_string_pretty(&original).unwrap();
    println!("{}", json);
    /*
    {
      "a": null,
      "d": null,
      "e": 0,
      "f": null,
      "g": null,
      "h": 0
    }
    */
    let parsed = serde_json::from_str::<A>(&json).unwrap();
    println!("{:?}", parsed);
    // A { a: None, b: None, c: None, d: None, e: Some(Some(0)), f: None, g: None, h: Some(Some(0)) }
    assert_eq!(original, parsed);
}
```

## `Vec<(String, String)>` -> `HashMap<String, String>`

```rust
let a = [
  ("hoge".into(), "fuga".into()),
  ("foo".into(), "bar".into())
].into_iter().collect::<HashMap<String, String>>();
```

## serde の enum に ToString と FromStr を実装する

```rust
#[derive(serde::Deserialize, serde::Serialize)]
enum Foo {
  Hoge,
  Huga
}

impl ToString for Foo {
    fn to_string(&self) -> String {
        serde_json::to_value(self)
            .unwrap()
            .as_str()
            .unwrap()
            .to_string()
    }
}

impl std::str::FromStr for Foo {
    type Err = serde_json::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_value(serde_json::Value::String(s.to_string()))
    }
}
```

## `HashMap<String, String>` -> `serde_json::map::Map<String, serde_json::Value>`

```rust
let hashmap: HashMap<String, String> = IntoIter::new([]).collect();
let map = hashmap
  .into_iter()
  .map(|(k, v)| (k, serde_json::Value::String(v)))
  .collect::<serde_json::map::Map<_, _>>();
```


## `HashMap<String, serde_json::Value>` -> `serde_json::map::Map<String, serde_json::Value>`

```rust
let hashmap: HashMap<String, String> = IntoIter::new([]).collect();
let map = hashmap
  .into_iter()
  .collect::<serde_json::map::Map<_, _>>();
```


## `HashMap<String, serde_json::Value>` -> `serde_json::Value::Object`

```rust
let hashmap: HashMap<String, String> = IntoIter::new([]).collect();
let map = hashmap
  .into_iter()
  .map(|(k, v)| (k, serde_json::Value::String(v)))
  .collect::<serde_json::map::Map<_, _>>();
let obj = serde_json::Value::Object(map);
```

## `HashMap<String, String>` -> `impl serde::Deserialize`

[serde_aux](https://docs.rs/serde-aux) を使うと string を int などに変換できる

```rust
use serde_aux::prelude::*;

#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
struct Obj{
  #[serde(deserialize_with = "deserialize_number_from_string")]
  id: i64,
  name: String,
}

let hashmap: HashMap<String, String> = IntoIter::new([]).collect();
let map = hashmap
  .into_iter()
  .map(|(k, v)| (k, serde_json::Value::String(v)))
  .collect::<serde_json::map::Map<_, _>>();
let obj = serde_json::Value::Object(map);
let o = serde_json::from_value::<Obj>(obj).unwrap();
```

## `serde_json::Value` -> `HashMap<String, serde_json::Value>`

```rust
let json = serde_json::json!({});
let o = serde_json::from_value::<serde_json::map::Map<String, serde_json::Value>>(json)?;
let map = o.into_iter().collect::<HashMap<_, _>>();
```

## `serde_json::Value` -> `HashMap<String, String>`

```rust
let json = serde_json::json!({});
let o = serde_json::from_value::<serde_json::map::Map<String, serde_json::Value>>(json)?;
let map = o.into_iter().map(|(k,v)| serde_json::from_value::<String>(v).map(|v|(k,v))).collect::<Result<HashMap<_, _>, _>>()?;
```


## STDIN -> `String`

```rust
let mut buf = String::new();
std::io::stdin().read_line(&mut buf).unwrap();
```

## `[&T]` -> `[T]` where `T: Copy`

https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.copied

```rust
let a = [1, 2, 3_u8];
let v_copied: Vec<_> = a.iter().copied().collect();
// let v_copied: Vec<_> = a.iter().map(|a| *a).collect(); // 同等
```
## `[T]` -> `[T]` where `T: Clone`

https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.cloned

```rust
let a = ["1".to_string(), "2".to_string(), "3".to_string()];
let v_copied: Vec<String> = a.iter().cloned().collect(); // 要素ごとに clone して Vec にする
// let v_copied: Vec<_> = a.iter().map(Clone::clone).collect(); // 同等
// let v_copied: Vec<_> = a.iter().map(|a| a.clone()).collect(); // 同等
// let v_copied: Vec<_> = a.clone().into_iter().collect(); // 最初に全部 clone する
```

## `Stream<Item=T>` -> `Vec<T>`

```rust
use futures::prelude::stream::StreamExt;
let src = futures::stream::iter(vec![1, 2, 3]);
let vct = src.collect::<Vec<_>>().await;
```

- https://docs.rs/futures/0.3.25/futures/prelude/stream/trait.StreamExt.html#method.collect

## `RangeInclusive<T>` -> `futures::stream::Stream<Item=T>`

```rust
let stream = futures::stream::iter(1..=3);
```

- https://users.rust-lang.org/t/lifetime-error-with-async-closure/42884

## `Stream<Item=Bytes>` -> `tokio::io::AsyncRead` -> `Stream<Item=String>`

非同期バイトストリームから改行ごとの文字列ストリームに変換する頻出パターン

```rs
use futures::stream::StreamExt;
use tokio::io::AsyncBufReadExt;

let src: BoxStream<'static, bytes::Bytes> = futures::stream::empty().boxed();
let aread = tokio_util::io::StreamReader::new(src);
let stream: BoxStream<'static, String> = tokio_stream::wrappers::LinesStream::new(aread.lines()).boxed();
```

- https://docs.rs/tokio/1.24.2/tokio/io/trait.AsyncRead.html
- https://docs.rs/tokio/1.24.2/tokio/io/trait.AsyncBufReadExt.html
- https://docs.rs/tokio-stream/0.1.11/tokio_stream/wrappers/struct.LinesStream.html
- https://docs.rs/tokio-util/0.7.4/tokio_util/io/struct.StreamReader.html

`tokio::io::AsyncRead` と `futures::io::AsyncRead` の違いについては以下を参照

- https://smallcultfollowing.com/babysteps/blog/2019/12/10/async-interview-2-cramertj-part-2/
- https://github.com/tokio-rs/tokio/pull/1744

`AsyncRead` と `Stream` 、`AsyncWrite` と `Sink` の違いについては次のブログが詳しい

- https://blog.yoshuawuyts.com/rust-streams/

## `tokio::io::AsyncRead` <-> `futures::io::AsyncRead`

`tokio_util::compat` を使う

```rust
use tokio_util::compat::FuturesAsyncReadCompatExt
let tokio_aread = fut_aread.compat();

use tokio_util::compat::TokioAsyncReadCompatExt;
let fut_aread = tokio_aread.compat();
```

- https://docs.rs/tokio-util/latest/tokio_util/compat/index.html

## `tokio::io::AsyncWrite` <-> `futures::io::AsyncWrite` 

同上

```rust
use tokio_util::compat::FuturesAsyncWriteCompatExt
let tokio_aread = fut_aread.compat();

use tokio_util::compat::TokioAsyncWriteCompatExt;
let fut_aread = tokio_aread.compat();
```

- https://docs.rs/tokio-util/latest/tokio_util/compat/index.html

## `futures::stream::StreamExt` <-> `tokio_stream::StreamExt`

- 型変換は存在しない
- 大本の `futures:stream::Stream` trait を実装していればどちらも使用可能

## DynamoDB AttributeValue JSON -> plain JSON

- `{"hash_key":{"S":"hoge"}}` を `{"hash_key":"hoge"}` にしたいとき
- `rusoto_dynamodb` の [`deserialize_structs`](https://docs.rs/crate/rusoto_dynamodb/latest/features) features と `serde_dynamo` を使う
- 一旦 [`rusoto_dynamodb::GetItemOutput`](https://docs.rs/rusoto_dynamodb/latest/rusoto_dynamodb/struct.GetItemOutput.html) でデシリアライズしておいて `HashMap<String, rusoto_dynamodb::AttributeValue>` を得てから [`serde_dynamo::from_attribute_value`](https://docs.rs/serde_dynamo/latest/serde_dynamo/rusoto_dynamodb_0_48/fn.from_attribute_value.html) で JSON に変換していく
- B や BS などには対応してないので注意
- aws-sdk-rust では[未対応の模様](https://github.com/awslabs/aws-sdk-rust/issues/269)

```toml
[dependencies]
rusoto_dynamodb = { version = "0.48.0", features = ["serialize_structs", "deserialize_structs"] }
serde = { version = "1.0.138", features = ["derive"] }
serde_dynamo = { version = "4.0.3", features = ["rusoto_dynamodb+0_48"] }
serde_json = "1.0.82"
```

```rust
fn dynamodb_item_to_json(
    item: std::collections::hash_map::HashMap<String, rusoto_dynamodb::AttributeValue>,
) -> Result<serde_json::Value, serde_dynamo::Error> {
    let o = item
        .into_iter()
        .map(|(k, v)| {
            serde_dynamo::from_attribute_value::<rusoto_dynamodb::AttributeValue, serde_json::Value>(v)
                .map(|v| (k, v))
        })
        .collect::<Result<Vec<_>, serde_dynamo::Error>>()?;
    let o = o.into_iter().collect::<serde_json::map::Map<String, serde_json::Value>>();
    Ok(serde_json::Value::from(o))
}

fn main() {
    let o = r#"{"hash_key":{"S":"hoge"}}"#;
    let o = serde_json::from_str::<serde_json::Value>(o).unwrap();
    let o = serde_json::json!({"Item": o});
    let o = serde_json::from_value::<rusoto_dynamodb::GetItemOutput>(o).unwrap().item.unwrap();
    let o = dynamodb_item_to_json(o).unwrap();
    let o = serde_json::to_string(&o).unwrap();
    assert_eq!(o, r#"{"hash_key":"hoge"}"#);
}
```

## `*mut c_char` -> `&Cstr` -> `&str`

- https://zenn.dev/eduidl/articles/f2fd959f220393

```rust
use std::os::raw::c_char;
use std::ffi::CStr;

let char_ptr: *mut c_char;
let cstr: &CStr = CStr::from_ptr(char_ptr);
let str_: &str = cstr.to_str().unwrap();
```

## `&str` -> `CString` -> `*mut c_char` 

- https://zenn.dev/eduidl/articles/f2fd959f220393

```rust
use std::ffi::CString;
use std::os::raw::c_char;

let str_: &str = "hoge";
let c_string: CString = CString::new(str_).unwrap();
let c_string_ptr: *const c_char = c_string.as_ptr();
```

## `*const u8` -> `&[u8]`

```rust
let a: *const u8 = std::ptr::null::<u8>();
let b: &u8 = unsafe{ &*a };
let c: &[u8] = std::slice::from_ref(b);
```

## ヒープを使わず `!Unpin` なstack 変数を使った自己参照構造体の作り方

```rust
#[derive(Debug)]
struct A<'a> {
    a: [u8; 32],
    a_ref: std::pin::Pin<&'a [u8]>,
}
fn main() {
    let mut a = std::pin::pin!(A {
        a: [0; 32],
        #[allow(deref_nullptr)]
        a_ref: std::pin::Pin::new(std::slice::from_ref(unsafe{ &*std::ptr::null::<u8>() })),
    });
    a.a_ref = std::pin::Pin::new(&a.a);
    // dbg!(a); // cannot move out of `a` because it is borrowed
    dbg!(&a);
}
```

## `Vec<impl Into<JsValue>>` -> `Array`

```rust
let arr = vec![0, 1]
  .into_iter()
  .map(js_sys::JsValue::from)
  .collect::<js_sys::Array>();
```