Borsh in Rustで「unresolved import `borsh`」エラー

ブロックチェーンのNEAR Protocolが提供している Borsh in Rust を使ったときのメモ。

Solana開発でもRustはBorshをよく使うため、利用シーンが非常に多い。
以下、公式サイト(自動翻訳)の説明。

borsh-rsはRustに組み込まれているBorshバイナリシリアライゼーションフォーマットです。

Borshは、ハッシュ用のBinary Object Representation Serializerの略です。一貫性、安全性、速度を優先し、厳密な仕様が付属しているため、セキュリティが重要なプロジェクトで使用することを目的としています。

現象

公式サイトをそのままコピペして、

main.rs

use borsh::{BorshSerialize, BorshDeserialize};

#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct A {
    x: u64,
    y: String,
}

#[test]
fn test_simple_struct() {
    let a = A {
        x: 3301,
        y: "liber primus".to_string(),
    };
    let encoded_a = a.try_to_vec().unwrap();
    let decoded_a = A::try_from_slice(&encoded_a).unwrap();
    assert_eq!(a, decoded_a);
}

cargo testを走らせるとエラーになる。

 % cargo test
   Compiling rust_sample v0.1.0 (/Users/user/Desktop/blockchain/rust_sample)
error[E0432]: unresolved import `borsh`
 --> src/main.rs:1:5
  |
1 | use borsh::{BorshSerialize, BorshDeserialize};
  |     ^^^^^ use of undeclared crate or module `borsh`

error: cannot determine resolution for the derive macro `BorshSerialize`
 --> src/main.rs:3:10
  |
3 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
  |          ^^^^^^^^^^^^^^
  |
  = note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the derive macro `BorshDeserialize`
 --> src/main.rs:3:26
  |
3 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
  |                          ^^^^^^^^^^^^^^^^
  |
  = note: import resolution is stuck, try simplifying macro imports

error[E0599]: no method named `try_to_vec` found for struct `A` in the current scope
  --> src/main.rs:15:23
   |
4  | struct A {
   | -------- method `try_to_vec` not found for this
...
15 |     let encoded_a = a.try_to_vec().unwrap();
   |                       ^^^^^^^^^^ method not found in `A`

error[E0599]: no function or associated item named `try_from_slice` found for struct `A` in the current scope
  --> src/main.rs:16:24
   |
4  | struct A {
   | -------- function or associated item `try_from_slice` not found for this
...
16 |     let decoded_a = A::try_from_slice(&encoded_a).unwrap();
   |                        ^^^^^^^^^^^^^^ function or associated item not found in `A`

Some errors have detailed explanations: E0432, E0599.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `rust_sample` due to 5 previous errors

原因

Borshがインストールされていない。

対策

Borshをインストールするように記述する。

Cargo.toml

[package]
name = "rust_sample"
version = "0.1.0"
edition = "2021"

[dependencies]
borsh = "0.9.1"
borsh-derive = "0.9.1"

加えて、デバッグ情報も追加。

main.rs

use borsh::{BorshSerialize, BorshDeserialize};

#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct A {
    x: u64,
    y: String,
}

#[test]
fn test_simple_struct() {
    let a = A {
        x: 3301,
        y: "liber primus".to_string(),
    };
    let encoded_a = a.try_to_vec().unwrap();
    let decoded_a = A::try_from_slice(&encoded_a).unwrap();
    assert_eq!(a, decoded_a);

    dbg!(a);
    dbg!(encoded_a);
    dbg!(decoded_a);
}

cargo testを実行。

% cargo test -- --nocapture
    Finished test [unoptimized + debuginfo] target(s) in 0.01s
     Running unittests (target/debug/deps/rust_sample-5676dc4c6fa69f76)

running 1 test
[src/main.rs:20] a = A {
    x: 3301,
    y: "liber primus",
}
[src/main.rs:21] encoded_a = [
    229,
    12,
    0,
    0,
    0,
    0,
    0,
    0,
    12,
    0,
    0,
    0,
    108,
    105,
    98,
    101,
    114,
    32,
    112,
    114,
    105,
    109,
    117,
    115,
]
[src/main.rs:22] decoded_a = A {
    x: 3301,
    y: "liber primus",
}
test test_simple_struct ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s