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}