mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-05-24 13:11: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,
|
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 {
|
impl MemoryInstance {
|
||||||
/// Create new linear memory instance.
|
/// Create new linear memory instance.
|
||||||
pub fn new(memory_type: &MemoryType) -> Result<Arc<Self>, Error> {
|
pub fn new(memory_type: &MemoryType) -> Result<Arc<Self>, Error> {
|
||||||
@ -48,36 +64,18 @@ impl MemoryInstance {
|
|||||||
|
|
||||||
/// Get data at given offset.
|
/// Get data at given offset.
|
||||||
pub fn get(&self, offset: u32, size: usize) -> Result<Vec<u8>, Error> {
|
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();
|
let buffer = self.buffer.read();
|
||||||
if buffer.len() < end {
|
let region = self.checked_region(&buffer, offset as usize, size)?;
|
||||||
return Err(Error::Memory(format!("trying to read region [{}..{}] in memory [0..{}]", begin, end, buffer.len())));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(buffer[begin..end].to_vec())
|
Ok(region.slice().to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set data at given offset.
|
/// Set data at given offset.
|
||||||
pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> {
|
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();
|
let mut buffer = self.buffer.write();
|
||||||
if buffer.len() < end {
|
let range = self.checked_region(&buffer, offset as usize, value.len())?.range();
|
||||||
return Err(Error::Memory(format!("trying to update region [{}..{}] in memory [0..{}]", begin, end, buffer.len())));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut mut_buffer = buffer.as_mut_slice();
|
buffer[range].copy_from_slice(value);
|
||||||
mut_buffer[begin..end].copy_from_slice(value);
|
|
||||||
|
|
||||||
Ok(())
|
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