use casper_wasmi_core::VirtualMemory;
pub struct ByteBuf {
mem: VirtualMemory,
len: usize,
}
impl ByteBuf {
const ALLOCATION_SIZE: usize =
validation::LINEAR_MEMORY_MAX_PAGES as usize * super::LINEAR_MEMORY_PAGE_SIZE.0;
pub fn new(len: usize) -> Result<Self, String> {
if len > isize::MAX as usize {
return Err("`len` should not exceed `isize::MAX`".into());
}
let mem = VirtualMemory::new(Self::ALLOCATION_SIZE).map_err(|error| error.to_string())?;
Ok(Self { mem, len })
}
pub fn realloc(&mut self, new_len: usize) -> Result<(), String> {
if new_len > Self::ALLOCATION_SIZE {
return Err(format!(
"tried to realloc virtual memory to a size of {} whereas the maximum is {} bytes",
new_len,
Self::ALLOCATION_SIZE,
));
}
self.len = new_len;
Ok(())
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
pub fn as_slice(&self) -> &[u8] {
&self.mem.data()[..self.len]
}
pub fn as_slice_mut(&mut self) -> &mut [u8] {
&mut self.mem.data_mut()[..self.len]
}
pub fn erase(&mut self) -> Result<(), String> {
self.mem = VirtualMemory::new(Self::ALLOCATION_SIZE).map_err(|error| error.to_string())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::ByteBuf;
const PAGE_SIZE: usize = 4096;
#[test]
fn byte_buf_shrink() {
let mut byte_buf = ByteBuf::new(PAGE_SIZE * 3).unwrap();
byte_buf.realloc(PAGE_SIZE * 2).unwrap();
}
#[test]
fn regression_realloc_too_big() {
let mut byte_buf = ByteBuf::new(100).unwrap();
assert!(byte_buf.realloc(ByteBuf::ALLOCATION_SIZE + 1).is_err());
}
#[test]
fn allocate_maximum_number_of_pages() {
let mut byte_buf = ByteBuf::new(100).unwrap();
byte_buf.realloc(ByteBuf::ALLOCATION_SIZE).unwrap();
}
}