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}