Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Bytes to_buffer and to_alloc_vec (#1231)
### What Add Bytes to_buffer and to_alloc_vec functions that provide access to the bytes in local guest memory. The to_buffer function provides access to the bytes in a statically specified buffer. The to_alloc_vec function is available only when the alloc feature is enabled and provides access to an alloc::vec::Vec containing the bytes. ### Why @tomerweller was talking to me about allocator usage in dev and testing when experimenting and costs are not that high, and it got me thinking that I mostly don't use the allocator because it's not trivial to get data into an allocated type. It's not that hard, but I don't think it's obvious and it's something we need to explain to people how to do. These functions provide two ways to get access to the data inside a variable length Bytes value, whether using the allocator or not. The first, `to_buffer` accepts as a constant generic parameter a buffer size, and returns the buffer filled with the contents of the bytes along with a `Range` that describes the slice of that buffer that contains the bytes. The bytes may not fill the full buffer and the range that case describes where the bytes begins (always 0) and ends. The function is usable regardless of whether the allocator is in use, and is suitable when a reasonable maximum size is known, but an exact size is not. The `to_alloc_vec` function requires the `alloc` feature as it dynamically allocates the memory required to store the bytes on the guest side. ### Costs Examples of costs of using these functions: #### `to_alloc_vec` The `to_alloc_vec` function with a small bytes value results in: - Contract Size: 3,835 bytes - CPU Used: 5,001,490 - Bytes Read: 3,992 - Fee Charged: 59,245 ``` #[contract] pub struct Contract; #[contractimpl] impl Contract { pub fn empty(env: Env) -> u32 { let bytes = Bytes::from_slice(&env, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); let len = bytes.to_alloc_vec().as_slice().len(); len as u32 } } ``` #### `to_buffer::<10>` The `to_buffer` function with a buffer size of 10 and a small bytes value results in: - Contract Size: 599 bytes - CPU Used: 3,828,048 - Bytes Read: 756 - Fee Charged: 44,351 ``` #[contract] pub struct Contract; #[contractimpl] impl Contract { pub fn empty(env: Env) -> u32 { let bytes = Bytes::from_slice(&env, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); let len = bytes.to_buffer::<10>().as_slice().len(); len as u32 } } ``` #### `to_buffer::<1024>` The `to_buffer` function with a buffer size of 1024 and a small bytes value results in: - Contract Size: 807 bytes - CPU Used: 3,914,448 - Bytes Read: 964 - Fee Charged: 45,418 ``` #[contract] pub struct Contract; #[contractimpl] impl Contract { pub fn empty(env: Env) -> u32 { let bytes = Bytes::from_slice(&env, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); let len = bytes.to_buffer::<10>().as_slice().len(); len as u32 } } ```
- Loading branch information