疑問

Q.「手を動かして考えればよくわかる高効率言語Rust書き方・作りかた」というRustの本を読んでたら、シーザー暗号のサンプルにて、文字から数値のキャストにi16を利用し、変換操作のあと、i8にして表示していた。
最初からi8でよいのでは?
また、u16やu8ではだめなのか?
という疑問がわいた。
A.よく読んだらRustでは文字は4バイト、Cなどでは1バイトと本文に記載があったので、それの影響かも。。。
また、後の確認の結果、result(文字列)に詰めるときはu8でないといけないし、それまでの変換処理では-を使うため符号ありの型を使う必要がありそう。

後学のために自分なりに検証してみる。

検証1 最初からi8でよいのでは?

ソース変更。左は本のソースを写経したものであり、右が一部修正したもの。

e1793c409203e3f6074bc503f5eefb6f

↓実行結果

> rustc .\ceasertest.rs; .\ceasertest.exe
> L ORYH BRX. => I LOVE YOU.

上記の変更だと正常に動く。 ただし、11行目のu8をi8にしたところ下記のエラーが出力された。

> rustc .\ceasertest.rs; .\ceasertest.exe
error[E0604]: only `u8` can be cast as `char`, not `i8`
  --> .\ceasertest.rs:11:21
   |
11 |         result.push((code as i8) as char);
   |                     ^^^^^^^^^^^^^^^^^^^^ invalid cast
   |
help: try casting from `u8` instead
  --> .\ceasertest.rs:11:21
   |
11 |         result.push((code as i8) as char);
   |                     ^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0604`.
L ORYH BRX. => I LOVE YOU.

「resultがString::new()で初期化(宣言?)した文字の配列(=文字列)のため、変数に格納する際にはchar(文字)にする必要がある。charへの変換はu8じゃないとダメ」というエラーのように見える。 i8とu8あたりの変換は扱っている数値が小さいからか問題なさそう。

検証2 また、u16やu8ではだめなのか?

全部u16バージョン

2142226af98fd4c6258ebd49669ee089

実行結果

> rustc .\ceasertest.rs; .\ceasertest.exe
error[E0600]: cannot apply unary operator `-` to type `u16`
  --> .\ceasertest.rs:18:29
   |
18 |     let dec = encrypt(&enc, -3);
   |                             ^^ cannot apply unary operator `-`
   |
   = note: unsigned values cannot be negated

error: aborting due to previous error

For more information about this error, try `rustc --explain E0600`.
L ORYH BRX. => I LOVE YOU.

引数で-を指定しているので、符号なしのu16は型の不一致で怒られているように見える。 まぁそう。

u8も同じ理由で正しくは動かなそう。