Student wall 🎨
最終更新
役に立ちましたか?
最終更新
役に立ちましたか?
2023年5月に開催されたのプロジェクトをRust言語で実装します。
Rustのプロジェクト「day3」を作成します。cargo new
コマンドを--lib
オプションを付与して実行します。
生成されたファイルは以下の通りです。
ライブラリを使用します。最新バージョンでよいかと思いますので、以下のように実行ます。
Canister上から関数が正しく呼び出させるようcrate-typeをcdylib
にします。
Canisterの定義を行います。
dfx.jsonの [canisters] > [day3] > [candid]項目に指定したファイルに、Canisterに配置するDappが提供する関数のI/Fを定義します。
※MotokoのResult (ok, err)とRust標準のResult (Ok, Err)で大文字小文字に違いがあります。MotokoとI/Fを合わせたい場合には別途Result型を定義してください。
cargo new
コマンドで生成されたlib.rsの中身をクリアして、day3用のプログラムを作成します。
writeMessage()
getMessage()
updateMessage()
deleteMessage()
upVote()
downVote()
getAllMessages()
getAllMessagesRanked()
Rust言語仕様の理解が十分でないため、作成したソースコードは所有権まわりをはじめ最適化されていない可能性がありますのでご注意ください。もしも、おかしな実装等が見つかりましたらが、ご指摘いただけますとさいわいです。
Canisterが提供する関数の名前がcamelCase
形式なのに対し、Rustは一般的にSnake_case
形式を推奨しているため、コンパイル時に以下のような警告が出ます。
先頭行に以下を入れておくことで、警告を抑止することができます。
扱うコンテンツを列挙型 (enum)として定義しています。
Textm Image, Videoのいずれかの値をとり、それぞれ異なるデータ型のデータを持ちます。
Contentとvote、creatorから構成される構造体を定義します。
Principal型はICのPrincipal IDを示しており投稿者も記録します。
Canister内に保持するデータは以下の2種類です。
メッセージ自動採番用
メッセージIDをキー、Messageデータを値とするBTreeMap
以下のようにスレッドローカルデータで保持するのが作法のようです。
※MotokoではHashMapが使われておりますが、ここではgetAllMessages()で順序性を維持できるようBTreeMapを使用しています。
TODO: IC色のあるUnitテスト方法について後日整理する
ソース中にIC色があるとUnitテストが上手く行えないようですので、以下のいずれかの方法でテストするとよいでしょう。
Canisterに配置してテストを行う
IC CDKのAPIを直接呼ばずに抽象化して、テスト時はスタブを使うようにする
後者の方法として、以下の記事が参考になりそうです。
Local Canisterを起動します。
--background
オプションでサービス常駐でき、--clean
を付与すると真っ新な状態でLocal canisterを起動できます。
Cargo.lockがディレクトリに存在しない場合dfx deploy
がエラーとなりますので、cargo generate-lockfile
を実行するとよいでしょう。
に相当するcandidを用意します。
と同じように、以下の関数を実装します。
やのようにUnitテストを記述してcargo test
を実行したところ、ロジックにICのPrincipal型が含まれることが原因で、「xxxx should only be called inside canisters.」のようなエラーが出ました。