mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-05-24 05:01:34 +00:00
Merge pull request #50 from NikVolf/mem-up
Memory extensions (copy + little refactoring)
This commit is contained in:
commit
73669922c9
@ -18,6 +18,22 @@ pub struct MemoryInstance {
|
||||
maximum_size: u32,
|
||||
}
|
||||
|
||||
struct CheckedRegion<'a, B: 'a> where B: ::std::ops::Deref<Target=Vec<u8>> {
|
||||
buffer: &'a B,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl<'a, B: 'a> CheckedRegion<'a, B> where B: ::std::ops::Deref<Target=Vec<u8>> {
|
||||
fn range(&self) -> ::std::ops::Range<usize> {
|
||||
self.offset..self.offset+self.size
|
||||
}
|
||||
|
||||
fn slice(&self) -> &[u8] {
|
||||
&self.buffer[self.range()]
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryInstance {
|
||||
/// Create new linear memory instance.
|
||||
pub fn new(memory_type: &MemoryType) -> Result<Arc<Self>, Error> {
|
||||
@ -48,36 +64,18 @@ impl MemoryInstance {
|
||||
|
||||
/// Get data at given offset.
|
||||
pub fn get(&self, offset: u32, size: usize) -> Result<Vec<u8>, Error> {
|
||||
let begin = offset as usize;
|
||||
let end = match begin.checked_add(size) {
|
||||
Some(end) => end,
|
||||
None => return Err(Error::Memory(format!("trying to read memory block of size {} from offset {}", size, offset))),
|
||||
};
|
||||
|
||||
let buffer = self.buffer.read();
|
||||
if buffer.len() < end {
|
||||
return Err(Error::Memory(format!("trying to read region [{}..{}] in memory [0..{}]", begin, end, buffer.len())));
|
||||
}
|
||||
let region = self.checked_region(&buffer, offset as usize, size)?;
|
||||
|
||||
Ok(buffer[begin..end].to_vec())
|
||||
Ok(region.slice().to_vec())
|
||||
}
|
||||
|
||||
/// Set data at given offset.
|
||||
pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> {
|
||||
let size = value.len();
|
||||
let begin = offset as usize;
|
||||
let end = match begin.checked_add(size) {
|
||||
Some(end) => end,
|
||||
None => return Err(Error::Memory(format!("trying to update memory block of size {} from offset {}", size, offset))),
|
||||
};
|
||||
|
||||
let mut buffer = self.buffer.write();
|
||||
if buffer.len() < end {
|
||||
return Err(Error::Memory(format!("trying to update region [{}..{}] in memory [0..{}]", begin, end, buffer.len())));
|
||||
}
|
||||
let range = self.checked_region(&buffer, offset as usize, value.len())?.range();
|
||||
|
||||
let mut mut_buffer = buffer.as_mut_slice();
|
||||
mut_buffer[begin..end].copy_from_slice(value);
|
||||
buffer[range].copy_from_slice(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -96,4 +94,37 @@ impl MemoryInstance {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_region<'a, B>(&self, buffer: &'a B, offset: usize, size: usize) -> Result<CheckedRegion<'a, B>, Error>
|
||||
where B: ::std::ops::Deref<Target=Vec<u8>>
|
||||
{
|
||||
let end = offset.checked_add(size)
|
||||
.ok_or(Error::Memory(format!("trying to access memory block of size {} from offset {}", size, offset)))?;
|
||||
|
||||
if end > buffer.len() {
|
||||
return Err(Error::Memory(format!("trying to access region [{}..{}] in memory [0..{}]", offset, end, buffer.len())));
|
||||
}
|
||||
|
||||
Ok(CheckedRegion {
|
||||
buffer: buffer,
|
||||
offset: offset,
|
||||
size: size,
|
||||
})
|
||||
}
|
||||
|
||||
/// Copy memory region
|
||||
pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> {
|
||||
let buffer = self.buffer.write();
|
||||
|
||||
let read_region = self.checked_region(&buffer, src_offset, len)?;
|
||||
let write_region = self.checked_region(&buffer, dst_offset, len)?;
|
||||
|
||||
unsafe { ::std::ptr::copy(
|
||||
buffer[read_region.range()].as_ptr(),
|
||||
buffer[write_region.range()].as_ptr() as *mut _,
|
||||
len,
|
||||
)}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user