zerocopy

zerocopy crate(Fuchsia 由来)は、バイト列と他の型の間を安全に変換するためのトレイトとマクロを提供します。

// 著作権 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

use zerocopy::{Immutable, IntoBytes};

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

#[repr(C)]
#[derive(Debug, Default, Immutable, IntoBytes)]
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]
    );
}

これは MMIO には適していません(volatile な読み書きを使用しないため)が、たとえば DMA によってハードウェアと共有される構造体や、何らかの外部インターフェース経由で送信される構造体を扱う際には有用です。

  • FromBytes は、どのようなバイトパターンでも有効である型に対して実装できるため、信頼できないバイト列からでも安全に変換できます。
  • これらの型に対して FromBytes を derive しようとすると失敗します。これは、RequestType が判別子として u32 の取り得るすべての値を使用しているわけではなく、そのためすべてのバイトパターンが有効ではないからです。
  • zerocopy::byteorder には、バイトオーダーを意識した数値プリミティブの型があります。
  • src/bare-metal/useful-crates/zerocopy-example/cargo run を使ってこの例を実行してください。(crate 依存関係があるため、Playground では実行されません。)