iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0

今天就分享 3 個 Rust 記憶體招式,copy_from_slicesplit_at_mutchunks_exact_mut

1. copy_from_slice

手上兩塊等長的 slice,要把 A 複到 B,不用自己寫 for 迴圈。用標準庫已經幫你做過 bounds 檢查的 copy_from_slice

fn stamp_prefix(dst: &mut [u8], prefix: &[u8]) {
    assert!(prefix.len() <= dst.len());
    let (head, _) = dst.split_at_mut(prefix.len());
    head.copy_from_slice(prefix);
}

長度不對會直接 panic 喔

fn overwrite(dst: &mut [u8], src: &[u8]) {
    dst.copy_from_slice(src); // 需要等長,否則 panic
}

2. split_at_mut

Rust 不允許同一個切片同時有兩個 &mut,但不重疊的兩段就沒問題。split_at_mut 幫你安全地把一塊切成兩塊。

fn fill_head_tail(buf: &mut [u8]) {
    let n = buf.len() / 2;
    let (head, tail) = buf.split_at_mut(n); // head 和 tail 互不重疊

    // 同時操作兩塊
    head.fill(0xAA);
    tail.fill(0x55);
}

你想「邊讀 A、邊把結果寫到 B」,但 A 和 B 其實在同一塊大陣列裡不同區段,split_at_mut 就是安全首選。

3. chunks_exact_mut

很多資料其實是「固定欄位長度」:例如 16-byte 的 UUID、20-byte 的 header… 與其手寫索引,不如讓切片自己吐出一塊一塊的 view。

fn xor_each_block_16(buf: &mut [u8], key: [u8; 16]) {
    for block in buf.chunks_exact_mut(16) {
        for (b, k) in block.iter_mut().zip(&key) {
            *b ^= *k;
        }
    }
    // 若長度不是 16 的倍數,剩下的在 remainder 處理
    let rem = buf.chunks_exact_mut(16).into_remainder();
    for (b, k) in rem.iter_mut().zip(&key) {
        *b ^= *k;
    }
}

chunks_exact_mut(4) 讓你自然地以「一筆」為單位處理,不用手算索引、也不會越界。

Vec 的配置姿勢

很多人會寫 Vec::with_capacity(len) 然後想「直接當作已填滿」使用,不行。安全作法用 resize 或建一個全零的:

fn new_zeroed(len: usize) -> Vec<u8> {
    vec![0u8; len]              // 配好 + 寫零(最安全)
    // 或者:
    // let mut v = Vec::with_capacity(len);
    // v.resize(len, 0);
    // v
}

set_len 是 unsafe,除非你真的保證之後每個位元組都會被正確寫入,否則不要用。


寫作業寫到兩眼一黑,為什麼作業這麼多啊?而且快考試了書還唸不完,我真的好爛:(


上一篇
Day 22|手機?
下一篇
Day 24|Borrow Checker:我不相信你
系列文
把前端加速到天花板:Rust+WASM 即插即用外掛26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言