use crate::{
device::{
common::{
check_and_trim, create_page, create_page_raw, flush_free_page, flush_page, load_free_page, load_page,
load_page_raw, mark_allocated, trim_or_free_page,
},
Device, FreePage, Page, ReadPage, SizeTool, UpdateList,
},
error::PERes,
};
use std::{io::Cursor, sync::Mutex};
pub struct MemoryDevice {
data: Mutex<Cursor<Vec<u8>>>,
limit: Option<u64>,
}
impl MemoryDevice {
pub fn new(limit: Option<u64>) -> PERes<MemoryDevice> {
Ok(MemoryDevice {
data: Mutex::new(Cursor::new(Vec::new())),
limit,
})
}
}
impl Device for MemoryDevice {
fn load_free_page(&self, page: u64) -> PERes<FreePage> {
load_free_page(&mut *self.data.lock().expect("memory device lock not poisoned"), page)
}
fn flush_free_page(&self, page: &FreePage) -> PERes<()> {
flush_free_page(&mut *self.data.lock().expect("memory device lock not poisoned"), page)
}
fn load_page(&self, page: u64) -> PERes<ReadPage> {
load_page(&mut *self.data.lock().expect("memory device lock not poisoned"), page)
}
fn load_page_if_exists(&self, page: u64) -> PERes<Option<ReadPage>> {
let mut data = self.data.lock().expect("memory device lock not poisoned");
if data.len()? <= page {
return Ok(None);
}
Ok(Some(load_page(&mut *data, page)?))
}
fn load_page_raw(&self, page: u64, size_exp: u8) -> PERes<Page> {
load_page_raw(
&mut *self.data.lock().expect("memory device lock not poisoned"),
page,
size_exp,
)
}
fn flush_page(&self, page: &Page) -> PERes<()> {
flush_page(&mut *self.data.lock().expect("memory device lock not poisoned"), page)
}
fn create_page_raw(&self, exp: u8) -> PERes<u64> {
create_page_raw(
&mut *self.data.lock().expect("memory device lock not poisoned"),
exp,
self.limit,
)
}
fn create_page(&self, exp: u8) -> PERes<Page> {
create_page(
&mut *self.data.lock().expect("memory device lock not poisoned"),
exp,
self.limit,
)
}
fn mark_allocated(&self, page: u64) -> PERes<u64> {
mark_allocated(&mut *self.data.lock().expect("memory device lock not poisoned"), page)
}
fn sync(&self) -> PERes<()> {
Ok(())
}
fn trim_or_free_page(&self, page: u64, update_list: &mut dyn UpdateList) -> PERes<()> {
trim_or_free_page(
&mut *self.data.lock().expect("memory device lock not poisoned"),
page,
update_list,
)
}
fn trim_end_pages(&self, update_list: &mut dyn UpdateList) -> PERes<()> {
while check_and_trim(
&mut *self.data.lock().expect("memory device lock not poisoned"),
update_list,
false,
)? {}
Ok(())
}
#[cfg(test)]
fn release_file_lock(&self) -> PERes<()> {
Ok(())
}
}