生ポインタを使う
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub struct SelfReferentialBuffer { data: [u8; 1024], cursor: *mut u8, } impl SelfReferentialBuffer { pub fn new() -> Self { let mut buffer = SelfReferentialBuffer { data: [0; 1024], cursor: std::ptr::null_mut() }; buffer.update_cursor(); buffer } // 危険: ムーブのたびに呼び出さなければならない pub fn update_cursor(&mut self) { self.cursor = self.data.as_mut_ptr(); } pub fn read(&self, n_bytes: usize) -> &[u8] { unsafe { let start = self.data.as_ptr(); let end = start.add(1024); let cursor = self.cursor as *const u8; assert!((start..=end).contains(&cursor), "cursor is out of bounds"); let available = end.offset_from(cursor) as usize; let len = n_bytes.min(available); std::slice::from_raw_parts(cursor, len) } } pub fn write(&mut self, bytes: &[u8]) { unsafe { let start = self.data.as_mut_ptr(); let end = start.add(1024); assert!((start..=end).contains(&self.cursor), "cursor is out of bounds"); let available = end.offset_from(self.cursor) as usize; let len = bytes.len().min(available); std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.cursor, len); self.cursor = self.cursor.add(len); } } }
ここではあまり時間をかけすぎないでください。
要点:
unsafeが頻繁に現れることを強調してください。これは、別の設計のほうがより適切かもしれないことを示唆しています。unsafeブロックに安全性コメントがありません。そのため、このコードは不健全です。unsafeブロックが広すぎます。よい実践では、より小さなunsafeブロックを使い、具体的な振る舞い、具体的な事前条件、具体的な安全性コメントを伴わせます。
質問:
Q: read() メソッドと write() メソッドは unsafe としてマークすべきですか?
A: はい。書き込みが行われるまでは self.cursor は null ポインタになるためです。