zerocopy

(Fuchsiaの)zerocopyクレートはバイトシーケンスとその他の型の変換を安全に行うためのトレイトやマクロを提供します。

use zerocopy::AsBytes;

#[repr(u32)]
#[derive(AsBytes, Debug, Default)]
enum RequestType {
    #[default]
    In = 0,
    Out = 1,
    Flush = 4,
}

#[repr(C)]
#[derive(AsBytes, Debug, Default)]
struct VirtioBlockRequest {
    request_type: RequestType,
    reserved: u32,
    sector: u64,
}

fn main() {
    let request = VirtioBlockRequest {
        request_type: RequestType::Flush,
        sector: 42,
        ..Default::default()
    };

    assert_eq!(
        request.as_bytes(),
        &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0]
    );
}

これは(volatile read、writeを使用していないため)MMIOには適してませんが、例えばDMAのようなハードウェアと共有するデータ構造あるいは外部インタフェースを通して送信するデータ構造を扱うに場合には有用です。

  • FromBytesはいかなるバイトパターンも有効な値となる型に対して実装することができ、信用できないバイトシーケンスからの安全な変換を可能にします。
  • RequestTypeはu32型のすべての値を有効なenum値として定義していないので、すべてのバイトパターンが有効とはならず、これらに対するFromBytesの導出はフェールするでしょう。
  • zerocopy::byteorderはバイトオーダを気にする数値プリミティブに関する型を提供します。
  • この例をsrc/bare-metal/useful-crates/zerocopy-example/においてcargo runととすることで実行してみましょう。(Playgroundではこの例が依存するクレートを利用できないため実行できません)