Skip to main content

basm_sdk_community/
memory.rs

1use core::alloc::Layout;
2use std::slice::from_raw_parts;
3
4/// Struct that represents a fat pointer where the upper 32 bits are the offset
5/// and the lower 32 bits are the size of the data.
6/// 
7/// Primarily used for passing data to and from the host environment.
8/// It is not reccomended to construct this directly, instead use `leak_to_shared_memory`
9/// 
10/// The maximum offset and size representable is 4GB each
11#[derive(Debug, PartialEq, Eq)]
12#[repr(transparent)]
13pub struct FatPointer(pub u64);
14
15impl FatPointer {
16    /// Location in memory where the data is stored
17    pub fn offset(&self) -> u32 {
18        (self.0 >> 32) as u32
19    }
20
21    /// Size of the data in bytes
22    pub fn size(&self) -> u32 {
23        self.0 as u32
24    }
25
26    /// Copies the data from the fat pointer into a newly allocated `Box<[u8]>`.
27    /// 
28    /// This is unsafe because it assumes that the data at the offset is valid. It is
29    /// the caller's responsibility to ensure that this is the case.
30    pub unsafe fn copy_data(&self) -> Box<[u8]> {
31        let slice = from_raw_parts(
32            self.offset() as *const u8,
33            self.size() as usize
34        );
35        Box::from(slice)
36    }
37}
38
39/// Creates a new allocation in memory and copies the provided data into it.
40/// Returns a `FatPointer` that points to the newly allocated memory.
41///
42/// This allocation is not tied to any lifetime and is the caller's responsibility
43/// to manage manually.
44pub fn leak_to_shared_memory(value: &[u8]) -> FatPointer {
45    let layout = Layout::array::<u8>(value.len()).unwrap();
46    unsafe {
47        let new_ptr = std::alloc::alloc(layout);
48        core::ptr::copy(value.as_ptr(), new_ptr, value.len());
49        FatPointer((new_ptr as u64) << 32u64 | value.len() as u64)
50    }
51}