use std::sync::{
Arc,
atomic::{AtomicU32, Ordering::SeqCst},
};
use wram::{AlignedBuf, BufferPool, DEFAULT_SECTOR_SIZE, MIN_SECTOR_SIZE, is_valid_sector_size};
use crate::{
device::Device,
error::{Error, Result},
};
pub struct NullDevice {
sector_size: usize,
start_segment: AtomicU32,
pool: Arc<BufferPool>,
}
impl NullDevice {
pub fn new() -> Result<Self> {
Self::with_sector_size(DEFAULT_SECTOR_SIZE)
}
pub fn with_sector_size(sector_size: usize) -> Result<Self> {
if !is_valid_sector_size(sector_size) {
return Err(Error::InvalidSectorSize {
size: sector_size,
min: MIN_SECTOR_SIZE,
});
}
Ok(Self {
sector_size,
start_segment: AtomicU32::new(0),
pool: BufferPool::new(sector_size)?,
})
}
}
impl Device for NullDevice {
#[inline]
fn sector_size(&self) -> usize {
self.sector_size
}
#[inline]
fn segment_size(&self) -> Option<u64> {
None
}
#[inline]
fn direct_io(&self) -> bool {
false
}
#[inline]
fn pool(&self) -> &Arc<BufferPool> {
&self.pool
}
async fn write_aligned(&self, _offset: u64, buf: AlignedBuf) -> (Result<usize>, AlignedBuf) {
(Ok(buf.len()), buf)
}
async fn read_aligned(&self, _offset: u64, mut buf: AlignedBuf) -> (Result<usize>, AlignedBuf) {
let n = buf.required_len().min(buf.capacity());
buf.as_allocated_slice_mut()[..n].fill(0);
unsafe { buf.set_len_unchecked(n) };
(Ok(n), buf)
}
#[inline]
async fn read_raw(&self, offset: u64, buf: AlignedBuf) -> (Result<usize>, AlignedBuf) {
self.read_aligned(offset, buf).await
}
async fn sync(&self) -> Result<()> {
Ok(())
}
#[inline]
fn get_file_size(&self, _segment_id: u32) -> Result<u64> {
Ok(u64::MAX)
}
async fn truncate_until_segment(&self, segment_id: u32) -> Result<()> {
self.start_segment.fetch_max(segment_id, SeqCst);
Ok(())
}
#[inline]
fn start_segment(&self) -> u32 {
self.start_segment.load(SeqCst)
}
}