Rust slice::as_chunks: แบ่ง slice เป็นกลุ่มขนาดคงที่โดยไม่ copy
งานที่ประมวลข้อมูลทีละ N ค่า เช่น RGB, พิกัด หรือ block protocol มักเริ่มจาก chunks_exact แล้วแปลง slice ย่อยเป็น array เองครับ ตั้งแต่ Rust 1.88 slice::as_chunks::<N>() คืน (&[[T; N]], &[T]) ทำให้ compiler รู้ขนาดแต่ละกลุ่มและยังไม่ copy ข้อมูล
WHY: ถาดขนาดตายตัวกับเศษที่วางข้าง ๆ
ลองแบ่งขนมลงถาดละสามชิ้น ถาดเต็มทุกใบมีรูปทรงเดียวกัน จึงส่งต่อให้ฟังก์ชันที่รับ [T; 3] ได้ทันที ส่วนที่ไม่ครบถาดถูกคืนเป็น remainder แทนการหายเงียบ ๆ ช่วยให้เราเลือกว่าจะ reject, pad หรือเก็บไว้รอข้อมูลรอบถัดไป
fn rgb_luma(bytes: &[u8]) -> (Vec<u16>, &[u8]) {
let (pixels, remainder) = bytes.as_chunks::<3>();
let luma = pixels
.iter()
.map(|[r, g, b]| u16::from(*r) + u16::from(*g) + u16::from(*b))
.collect();
(luma, remainder)
}
#[test]
fn groups_without_copying() {
let input = [10, 20, 30, 1, 2, 3, 99];
let (luma, rest) = rgb_luma(&input);
assert_eq!(luma, vec![60, 6]);
assert_eq!(rest, &[99]);
}
#[test]
fn short_input_becomes_remainder() {
let (luma, rest) = rgb_luma(&[1, 2]);
assert!(luma.is_empty());
assert_eq!(rest, &[1, 2]);
}
Const generic ทำให้ขอบเขตชัด
N เป็น const generic จึงรู้ตอน compile ว่าแต่ละ chunk ยาวเท่าไร แต่ N = 0 จะ panic ตอนเรียก ไม่ใช่ผลลัพธ์ว่าง หากขนาดมาจากผู้ใช้ต้อง validate ก่อนและอาจใช้ chunks_exact(runtime_size) แทน
ทั้ง chunks และ remainder borrow จาก input ห้ามเก็บนานกว่าต้นฉบับ และ as_chunks_mut เปิดให้แก้ backing slice เดิม จึงต้องระวัง alias ตามกติกา borrow ของ Rust
Recap
- ใช้
as_chunks::<N>เมื่อขนาดกลุ่มรู้ตอน compile - จัดการ remainder อย่างตั้งใจ
- ห้ามใช้
N = 0 - จำว่าเป็น view แบบยืมข้อมูล ไม่ใช่การ copy