回答編集履歴
3
理解を深めるために必要になりそうな項目を追記しました
answer
CHANGED
|
@@ -68,4 +68,68 @@
|
|
|
68
68
|
|
|
69
69
|
期待通りの値になったようです。
|
|
70
70
|
|
|
71
|
-
このように16進数文字列を`hex::decode()`でデコードしてから、`H512::from_slice()`に渡してみてください。
|
|
71
|
+
このように16進数文字列を`hex::decode()`でデコードしてから、`H512::from_slice()`に渡してみてください。
|
|
72
|
+
|
|
73
|
+
----
|
|
74
|
+
|
|
75
|
+
----
|
|
76
|
+
|
|
77
|
+
**追記 2019-08-07**
|
|
78
|
+
|
|
79
|
+
> 最後に恐縮ですが、この辺りの理解を深める為のリソースでオススメ等ございましたら後学の為に共有頂けると助かります。
|
|
80
|
+
|
|
81
|
+
質問者さまがどの程度の知識をお持ちなのかわからないので、理解を深めるために必要になりそうな項目を全て列挙します。すでにご存知のものについては無視してください。
|
|
82
|
+
|
|
83
|
+
----
|
|
84
|
+
|
|
85
|
+
**整数と文字列の内部表現(メモリ上でのデータ形式)の違いについて確認する**
|
|
86
|
+
|
|
87
|
+
整数の内部表現
|
|
88
|
+
|
|
89
|
+
- 2進法と16進法(1バイトの情報はちょうど16進数2桁で表せる)
|
|
90
|
+
- 8ビット整数、32ビット整数、64ビット整数など、加減乗除などの演算をCPUがサポートしている形式
|
|
91
|
+
+ Rustなら`u8`, `i32`, `usize`型などのスカラ型
|
|
92
|
+
- 多バイト長整数(または多倍長整数) ・・・512ビット(64バイト)整数など、演算をCPUがサポートしていない形式
|
|
93
|
+
+ バイト列で表現することが多い。(Rustなら`Vec<u8>`など)
|
|
94
|
+
+ Rustではたとえばnum-bigintクレートが可変長の多バイト長整数を提供する。primitive-typesクレートはEthereumなどで使われている固定長の多バイト長整数を提供する。(可変長:整数の大きさによってバイト数が変わる、固定長:バイト数が固定されている)
|
|
95
|
+
- バイトの並び順 ・・・リトルエンディアンとビッグエンディアン
|
|
96
|
+
|
|
97
|
+
文字列の内部表現(文字コードとエンコーディング)
|
|
98
|
+
|
|
99
|
+
- Rustの文字列型(`str`と`String`)はUTF-8エンコーディングを使用している
|
|
100
|
+
- 整数と文字列では内部表現が異なる
|
|
101
|
+
+ たとえば32ビット符号付き整数(Rustでは`i32`型)の`-42`と、文字列(Rustでは`&str`または`String`型)の`"-42"`ではメモリ上に異なる情報が格納される
|
|
102
|
+
+ Rustで文字列`"-42"`を`i32`型の`-42`に変換するには、`str`型の`parse`メソッドを使う(例:`"-42".parse::<i32>()`)
|
|
103
|
+
+ その逆の変換をするには`ToString`トレイトの`to_string`メソッドや、`format!`マクロを使う
|
|
104
|
+
|
|
105
|
+
**内部表現から外部表現への変換と、その逆の変換について確認する**
|
|
106
|
+
|
|
107
|
+
- 外部表現はデータをファイルに保存したり、他のプログラムとデータをやりとりするときに必要となる
|
|
108
|
+
- 外部表現にはバイナリデータ(`println!`の`"{}"`などで表示できない生のバイト列)とテキストデータ(表示可能な文字で構成された文字列)がある
|
|
109
|
+
|
|
110
|
+
たとえばJSON形式
|
|
111
|
+
- JSONは32ビット整数や文字列などは表現できるが、多バイト長整数のようなデータは直接表現できない
|
|
112
|
+
- JSONはバイナリデータを扱えない
|
|
113
|
+
- 多バイト長整数のようなデータはテキストデータに変換(エンコード)する必要がある
|
|
114
|
+
|
|
115
|
+
エンコード形式には、16進数文字列や、Base64などがよく使われる
|
|
116
|
+
- 前者よりも後者の方が変換後のデータサイズが小さい
|
|
117
|
+
- 一般的にハッシュデータは前者、それ以外は後者が好んで使われるが、特に決まりがあるわけではない
|
|
118
|
+
|
|
119
|
+
----
|
|
120
|
+
|
|
121
|
+
これらの概念についてはRustに特化した包括的な説明はなさそうなので、「コンピュータにおける情報の表現」をC言語などを使って解説しているサイトを見るのがいいのかなと思います。たとえば基本的な部分は[https://www.seiai.ed.jp/sys/text/cs/index.html](https://www.seiai.ed.jp/sys/text/cs/index.html)のようなサイトを参照して、そこにない情報(多バイト長整数、16進数文字列、Base64エンコーディングなど)については、それぞれ検索して、出てきた記事を読んでみるといったイメージです。
|
|
122
|
+
|
|
123
|
+
もしこれらの概念についてはすでに理解されていて、Rustではどう扱えばいいのかだけを知りたいのなら、(宣伝になってしまいますが)たとえば私が共著で執筆した書籍で文字列などについては少し詳しく解説していますので参考になるかもしれません。今年の5月に発売されたばかりの書籍ですので、大きな書店なら置いてあると思います。
|
|
124
|
+
|
|
125
|
+
[実践Rust入門](https://gihyo.jp/book/2019/978-4-297-10559-4/)(技術評論社) ISBN978-4-297-10559-4
|
|
126
|
+
|
|
127
|
+
- 4-2-3 固定精度の整数 ・・・内部表現の説明はないのですが、桁あふれの扱いなどを説明しています
|
|
128
|
+
- 4-2-5 文字 ・・・Unicodeスカラ値について説明しています
|
|
129
|
+
- 4-3-4 文字列スライス(`str`型) ・・・UTF-8エンコーディングなどもごく簡単にですが説明しています
|
|
130
|
+
- 5-2-4 `String` ・・・`to_string()`と`parse()`、`String`と`str`の比較(図で説明)、など
|
|
131
|
+
- 7-9 ライフタイムの詳細:簡単なベクタの実装 ・・・`String`の内部表現にも使われている`Vec<T>`を真似た型を実装することで、Rustにおける所有権の概念に加えて、データの内部表現についても学べます
|
|
132
|
+
|
|
133
|
+
書籍の概要については共著者のκeenさんが書かれたブログ記事が参考になると思います。
|
|
134
|
+
|
|
135
|
+
[実践Rust入門を書いたよ](https://keens.github.io/blog/2019/04/21/jissenrustnyuumon_wokaitayo/)
|
2
誤字を修正しました
answer
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
let r = "0x148de18c21abe5c1ea727e3204ccbb4cad5f4a9da758cd957f5a6d19454d47b1cb25790cfedc643d1ab730bff97c1d4283da3faacd96b7df0bfb7bdcf3d4d029".to_string();
|
|
54
54
|
// 先頭に"0x"があるとhexクレートでデコードできないので削除する
|
|
55
55
|
let r = r.replacen("0x", "", 1);
|
|
56
|
-
//
|
|
56
|
+
// 16進数文字列をhexクレートでデコードする
|
|
57
57
|
let bytes = hex::decode(&r).unwrap(); // Vec<u8>型
|
|
58
58
|
hexdump(&bytes);
|
|
59
59
|
```
|
1
説明を少し追加しました
answer
CHANGED
|
@@ -37,13 +37,17 @@
|
|
|
37
37
|
32 39
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
一方、`H512::from_slice()`が期待しているのは、文字コードではなく、`&[0x14, 0x8d, 0xe1, 0x8c, ..]`といった数値データの並びになります。つまり`str::as_bytes()`ではなく、16進数の文字列を数値データの並びへと変換する関数が必要です。
|
|
40
|
+
一方、`H512::from_slice()`が期待しているのは、文字コードの並びではなく、`&[0x14, 0x8d, 0xe1, 0x8c, ..]`といった数値データの並びになります。つまり`str::as_bytes()`ではなく、16進数の文字列を数値データの並びへと変換する関数が必要です。
|
|
41
41
|
|
|
42
42
|
そのような関数は標準ライブラリのメソッドを使って簡単に自作できると思いますが、すでに`hex`というクレートがあるのでそれを使う方法を紹介します。
|
|
43
43
|
|
|
44
44
|
先ほどのコードを`hex`クレートで書き換えると以下のようになります。
|
|
45
45
|
|
|
46
46
|
```rust
|
|
47
|
+
// Cargo.tomlに以下を追加
|
|
48
|
+
// [dependencies]
|
|
49
|
+
// hex = "0.3"
|
|
50
|
+
|
|
47
51
|
use hex;
|
|
48
52
|
|
|
49
53
|
let r = "0x148de18c21abe5c1ea727e3204ccbb4cad5f4a9da758cd957f5a6d19454d47b1cb25790cfedc643d1ab730bff97c1d4283da3faacd96b7df0bfb7bdcf3d4d029".to_string();
|