inkpad_sandbox/
memory.rs

1use crate::Sandbox;
2use inkpad_executor::{Error, Result};
3use inkpad_std::{vec, Vec};
4use inkpad_support::traits::Ext;
5use parity_scale_codec::{Decode, DecodeAll, Encode};
6
7impl Sandbox {
8    /// Read designated chunk from the sandbox memory.
9    pub fn read_sandbox_memory(&self, ptr: u32, len: u32) -> Result<Vec<u8>> {
10        let mut buf = vec![0u8; len as usize];
11        self.read_sandbox_memory_into_buf(ptr, &mut buf)?;
12        Ok(buf.to_vec())
13    }
14
15    /// Read designated chunk from the sandbox into the supplied buffer
16    pub fn read_sandbox_memory_into_buf(&self, ptr: u32, buf: &mut [u8]) -> Result<()> {
17        self.memory()
18            .ok_or(Error::CodeNotFound)?
19            .get(ptr, buf)
20            .map_err(|_| Error::OutOfBounds)?;
21        Ok(())
22    }
23
24    /// Read designated chunk from the sandbox memory and attempt to decode into the specified type.
25    pub fn read_sandbox_memory_as<D: Decode>(&mut self, ptr: u32, len: u32) -> Result<D> {
26        let buf = self.read_sandbox_memory(ptr, len)?;
27        let decoded = D::decode_all(&buf[..]).map_err(|_| Error::DecodeRuntimeValueFailed)?;
28        Ok(decoded)
29    }
30
31    /// Write the given buffer to the designated location in the sandbox memory.
32    pub fn write_sandbox_memory(&mut self, ptr: u32, buf: &[u8]) -> Result<()> {
33        self.memory()
34            .ok_or(Error::CodeNotFound)?
35            .set(ptr, buf)
36            .map_err(|_| Error::OutOfBounds)
37    }
38
39    /// Write the given buffer and its length to the designated locations in sandbox memory
40    ///
41    /// buf -> memory
42    pub fn write_sandbox_output(
43        &mut self,
44        out_ptr: u32,
45        out_len_ptr: u32,
46        buf: &[u8],
47    ) -> Result<()> {
48        let buf_len = buf.len() as u32;
49        let len: u32 = self.read_sandbox_memory_as(out_len_ptr, 4)?;
50
51        if len < buf_len {
52            return Err(Error::OutputBufferTooSmall);
53        }
54
55        let memory = self.memory().ok_or(Error::CodeNotFound)?;
56        memory
57            .set(out_ptr, buf)
58            .and_then(|_| memory.set(out_len_ptr, &buf_len.encode()))
59            .map_err(|_| Error::OutOfBounds)?;
60
61        Ok(())
62    }
63}