Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Частичная инициализация

// 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: мы инициализировали ровно 'len' байт `buf` текстом в 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> говорит компилятору зарезервировать место, но пока не трогать память.

Вопрос: какая часть фрагмента кода выполняет роль, похожую на .assume_init()? Ответ: приведение указателя и неявное чтение.

Нельзя вызвать assume_init() для всего массива: это было бы некорректно, потому что большинство элементов остаются неинициализированными. Вместо этого мы приводим указатель из *const MaybeUninit<u8> к *const u8 и строим срез, охватывающий только инициализированную часть.