部分的な初期化

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0

use std::mem::MaybeUninit;

fn main() {
    // let mut buf = [0u8; 2048];
    let mut buf = [const { MaybeUninit::<u8>::uninit() }; 2048];

    let external_data = b"Hello, Rust!";
    let len = external_data.len();

    for (dest, src) in buf.iter_mut().zip(external_data) {
        dest.write(*src);
    }

    // SAFETY: `buf` のうちちょうど `len` バイトを UTF-8 テキストで初期化した
    let text: &str = unsafe {
        let ptr: *const u8 = buf.as_ptr().cast::<u8>();
        let init: &[u8] = std::slice::from_raw_parts(ptr, len);
        std::str::from_utf8_unchecked(init)
    };

    println!("{text}");
}

このコードは、何らかの外部ソースからデータを受信する状況をシミュレートしています。

外部ソースからバッファへバイト列を読み込むとき、通常は受信するバイト数がわかりません。MaybeUninit<T> を使うと、冗長な初期化パスのコストを払うことなく、バッファを一度だけ確保できます。

標準的な構文(buf = [0u8; 2048])で配列を作成すると、バッファ全体がゼロで埋められます。MaybeUninit<T> は、領域は確保するものの、まだそのメモリには触れないようコンパイラに伝えます。

Q: このコードスニペットのどの部分が .assume_init() と同様の役割を果たしていますか? A: ポインタのキャストと暗黙の読み出しです。

配列全体に対して assume_init() を呼び出すことはできません。ほとんどの要素が未初期化のままなので、それは不健全です。代わりに、ポインタを *const MaybeUninit<u8> から *const u8 にキャストし、初期化済みの部分だけを対象とするスライスを構築します。