1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
use holochain_wasmer_common::*; /// Allocate bytes that won't be dropped by the allocator. /// Return the pointer to the leaked allocation so the host can write to it. #[no_mangle] #[inline(always)] pub extern "C" fn __allocate(len: Len) -> GuestPtr { let dummy: Vec<u8> = Vec::with_capacity(len as usize); let ptr = dummy.as_ptr() as GuestPtr; let _ = core::mem::ManuallyDrop::new(dummy); ptr } /// Free an allocation. /// Needed because we leak memory every time we call `__allocate` and `write_bytes`. #[no_mangle] #[inline(always)] pub extern "C" fn __deallocate(guest_ptr: GuestPtr, len: Len) { let _: Vec<u8> = unsafe { Vec::from_raw_parts(guest_ptr as *mut u8, len as usize, len as usize) }; } /// Attempt to consume bytes from a known guest_ptr and len. /// /// Consume in this context means take ownership of previously forgotten data. /// /// This needs to work for bytes written into the guest from the host and for bytes written with /// the write_bytes() function within the guest. #[inline(always)] pub fn consume_bytes(guest_ptr: GuestPtr, len: Len) -> Vec<u8> { unsafe { Vec::from_raw_parts( // must match the pointer produced by the original allocation exactly guest_ptr as *mut u8, // this is the full length of the allocation as we want all the bytes len as usize, // must match the capacity set during the original allocation exactly len as usize, ) } } /// Attempt to write a slice of bytes. /// /// This is identical to the following: /// - host has some slice of bytes /// - host calls __allocate with the slice length /// - guest returns GuestPtr to the host /// - host writes the bytes into the guest at GuestPtr location /// - host hands the GuestPtr back to the guest /// /// In this case everything happens within the guest and a GuestPtr is returned if successful. /// /// This also leaks the written bytes, exactly like the above process. /// /// This facilitates the guest handing a GuestPtr back to the host as the _return_ value of guest /// functions so that the host can read the _output_ of guest logic from a pointer. /// /// The host MUST ensure either __deallocate is called or the entire wasm memory is dropped. #[inline(always)] pub fn write_bytes(v: Vec<u8>) -> GuestPtr { let ptr: GuestPtr = v.as_ptr() as GuestPtr; let _ = core::mem::ManuallyDrop::new(v); ptr }