solana_transaction_context/vm_slice.rs
1// The VmSlice class is used for cases when you need a slice that is stored in the BPF
2// interpreter's virtual address space. Because this source code can be compiled with
3// addresses of different bit depths, we cannot assume that the 64-bit BPF interpreter's
4// pointer sizes can be mapped to physical pointer sizes. In particular, if you need a
5// slice-of-slices in the virtual space, the inner slices will be different sizes in a
6// 32-bit app build than in the 64-bit virtual space. Therefore instead of a slice-of-slices,
7// you should implement a slice-of-VmSlices, which can then use VmSlice::translate() to
8// map to the physical address.
9// This class must consist only of 16 bytes: a u64 ptr and a u64 len, to match the 64-bit
10// implementation of a slice in Rust. The PhantomData entry takes up 0 bytes.
11
12use std::marker::PhantomData;
13
14#[repr(C)]
15#[derive(Debug, PartialEq)]
16pub struct VmSlice<T> {
17 ptr: u64,
18 len: u64,
19 resource_type: PhantomData<T>,
20}
21
22impl<T> VmSlice<T> {
23 pub fn new(ptr: u64, len: u64) -> Self {
24 VmSlice {
25 ptr,
26 len,
27 resource_type: PhantomData,
28 }
29 }
30
31 pub fn ptr(&self) -> u64 {
32 self.ptr
33 }
34
35 pub fn len(&self) -> u64 {
36 self.len
37 }
38
39 pub fn is_empty(&self) -> bool {
40 self.len == 0
41 }
42
43 /// # Safety
44 /// Set a new length for the mapped account.
45 /// This function is not safe to use if not coupled with the respective change in
46 /// the underlying vector.
47 pub unsafe fn set_len(&mut self, new_len: u64) {
48 self.len = new_len;
49 }
50}