multiversx_chain_vm/
mem_conv.rs

1use multiversx_chain_vm_executor::{MemLength, MemPtr};
2
3pub fn with_mem_ptr<F, R>(bytes: &[u8], f: F) -> R
4where
5    F: FnOnce(MemPtr, MemLength) -> R,
6{
7    f(bytes.as_ptr() as MemPtr, bytes.len() as MemLength)
8}
9
10pub fn with_mem_ptr_mut<F, R>(bytes: &mut [u8], f: F) -> R
11where
12    F: FnOnce(MemPtr, MemLength) -> R,
13{
14    f(bytes.as_ptr() as MemPtr, bytes.len() as MemLength)
15}
16
17/// Interprets an offset and length (both isize) as a byte slice.
18///
19/// # Safety
20///
21/// Should only be called with arguments that originate from `with_mem_ptr`.
22pub unsafe fn with_bytes<F, R>(offset: MemPtr, length: MemLength, f: F) -> R
23where
24    F: FnOnce(&[u8]) -> R,
25{
26    let bytes = std::ptr::slice_from_raw_parts(offset as *const u8, length as usize);
27    f(&*bytes)
28}
29
30/// Interprets an offset and length (both isize) as a mutable byte slice.
31///
32/// # Safety
33///
34/// Should only be called with arguments that originate from `with_mem_ptr_mut`.
35pub unsafe fn with_bytes_mut<F, R>(offset: MemPtr, length: MemLength, f: F) -> R
36where
37    F: FnOnce(&mut [u8]) -> R,
38{
39    let bytes = std::ptr::slice_from_raw_parts_mut(offset as *mut u8, length as usize);
40    f(&mut *bytes)
41}
42
43#[cfg(test)]
44mod test {
45    use super::*;
46
47    #[test]
48    fn test_mem_ptr_conversion() {
49        assert_mem_conv_sound(vec![]);
50        assert_mem_conv_sound(vec![1]);
51        assert_mem_conv_sound(vec![1, 2, 3]);
52    }
53
54    fn assert_mem_conv_sound(data: Vec<u8>) {
55        let cloned = with_mem_ptr(data.as_slice(), |offset, length| unsafe {
56            with_bytes(offset, length, |bytes| bytes.to_vec())
57        });
58        assert_eq!(data, cloned);
59    }
60
61    #[test]
62    fn test_mem_ptr_mut() {
63        let mut data = vec![1, 2, 3];
64        with_mem_ptr_mut(data.as_mut_slice(), |offset, length| unsafe {
65            with_bytes_mut(offset, length, |bytes| {
66                for b in bytes {
67                    *b += 1;
68                }
69            })
70        });
71        assert_eq!(data, vec![2, 3, 4]);
72    }
73}