diff --git a/src/tree_store/page_store/cached_file.rs b/src/tree_store/page_store/cached_file.rs index 7310c165..6b08eff0 100644 --- a/src/tree_store/page_store/cached_file.rs +++ b/src/tree_store/page_store/cached_file.rs @@ -3,6 +3,7 @@ use crate::tree_store::LEAF; use crate::{DatabaseError, Result, StorageBackend, StorageError}; use std::collections::BTreeMap; use std::io; +use std::mem::ManuallyDrop; use std::ops::{Index, IndexMut}; use std::slice::SliceIndex; #[cfg(feature = "cache_metrics")] @@ -30,23 +31,27 @@ impl CachePriority { pub(super) struct WritablePage { buffer: Arc>, offset: u64, - data: Option>, + data: ManuallyDrop>, priority: CachePriority, } impl WritablePage { pub(super) fn mem(&self) -> &[u8] { - self.data.as_ref().unwrap() + &self.data } pub(super) fn mem_mut(&mut self) -> &mut [u8] { - Arc::get_mut(self.data.as_mut().unwrap()).unwrap() + let data = Arc::get_mut(&mut self.data); + debug_assert!(data.is_some()); + // SAFETY: `self` has the sole reference to `data`. + unsafe { data.unwrap_unchecked() } } } impl Drop for WritablePage { fn drop(&mut self) { - let data = self.data.take().unwrap(); + // SAFETY: `drop` is called at most once + let data = unsafe { ManuallyDrop::take(&mut self.data) }; self.buffer .lock() .unwrap() @@ -487,7 +492,7 @@ impl PagedCachedFile { Ok(WritablePage { buffer: self.write_buffer.clone(), offset, - data: Some(data), + data: ManuallyDrop::new(data), priority, }) }