|
| 1 | +//! Basic low-level memory operations. |
| 2 | +//! |
| 3 | +//! Within the SBF environment, these are implemented as syscalls and executed by |
| 4 | +//! the runtime in native code. |
| 5 | +
|
| 6 | +#[cfg(target_os = "solana")] |
| 7 | +use crate::syscalls; |
| 8 | + |
| 9 | +/// Like C `memcpy`. |
| 10 | +/// |
| 11 | +/// # Arguments |
| 12 | +/// |
| 13 | +/// - `dst` - Destination |
| 14 | +/// - `src` - Source |
| 15 | +/// - `n` - Number of bytes to copy |
| 16 | +/// |
| 17 | +/// # Errors |
| 18 | +/// |
| 19 | +/// When executed within a SBF program, the memory regions spanning `n` bytes |
| 20 | +/// from from the start of `dst` and `src` must be mapped program memory. If not, |
| 21 | +/// the program will abort. |
| 22 | +/// |
| 23 | +/// The memory regions spanning `n` bytes from `dst` and `src` from the start |
| 24 | +/// of `dst` and `src` must not overlap. If they do, then the program will abort |
| 25 | +/// or, if run outside of the SBF VM, will panic. |
| 26 | +/// |
| 27 | +/// # Safety |
| 28 | +/// |
| 29 | +/// This function does not verify that `n` is less than or equal to the |
| 30 | +/// lengths of the `dst` and `src` slices passed to it — it will copy |
| 31 | +/// bytes to and from beyond the slices. |
| 32 | +/// |
| 33 | +/// Specifying an `n` greater than either the length of `dst` or `src` will |
| 34 | +/// likely introduce undefined behavior. |
| 35 | +#[inline] |
| 36 | +pub unsafe fn sol_memcpy(dst: &mut [u8], src: &[u8], n: usize) { |
| 37 | + #[cfg(target_os = "solana")] |
| 38 | + syscalls::sol_memcpy_(dst.as_mut_ptr(), src.as_ptr(), n as u64); |
| 39 | + |
| 40 | + #[cfg(not(target_os = "solana"))] |
| 41 | + core::hint::black_box((dst, src, n)); |
| 42 | +} |
| 43 | + |
| 44 | +/// Like C `memmove`. |
| 45 | +/// |
| 46 | +/// # Arguments |
| 47 | +/// |
| 48 | +/// - `dst` - Destination |
| 49 | +/// - `src` - Source |
| 50 | +/// - `n` - Number of bytes to copy |
| 51 | +/// |
| 52 | +/// # Errors |
| 53 | +/// |
| 54 | +/// When executed within a SBF program, the memory regions spanning `n` bytes |
| 55 | +/// from from `dst` and `src` must be mapped program memory. If not, the program |
| 56 | +/// will abort. |
| 57 | +/// |
| 58 | +/// # Safety |
| 59 | +/// |
| 60 | +/// The same safety rules apply as in [`ptr::copy`]. |
| 61 | +/// |
| 62 | +/// [`ptr::copy`]: https://doc.rust-lang.org/std/ptr/fn.copy.html |
| 63 | +#[inline] |
| 64 | +pub unsafe fn sol_memmove(dst: *mut u8, src: *mut u8, n: usize) { |
| 65 | + #[cfg(target_os = "solana")] |
| 66 | + syscalls::sol_memmove_(dst, src, n as u64); |
| 67 | + |
| 68 | + #[cfg(not(target_os = "solana"))] |
| 69 | + core::hint::black_box((dst, src, n)); |
| 70 | +} |
| 71 | + |
| 72 | +/// Like C `memcmp`. |
| 73 | +/// |
| 74 | +/// # Arguments |
| 75 | +/// |
| 76 | +/// - `s1` - Slice to be compared |
| 77 | +/// - `s2` - Slice to be compared |
| 78 | +/// - `n` - Number of bytes to compare |
| 79 | +/// |
| 80 | +/// # Errors |
| 81 | +/// |
| 82 | +/// When executed within a SBF program, the memory regions spanning `n` bytes |
| 83 | +/// from from the start of `dst` and `src` must be mapped program memory. If not, |
| 84 | +/// the program will abort. |
| 85 | +/// |
| 86 | +/// # Safety |
| 87 | +/// |
| 88 | +/// It does not verify that `n` is less than or equal to the lengths of the |
| 89 | +/// `dst` and `src` slices passed to it — it will read bytes beyond the |
| 90 | +/// slices. |
| 91 | +/// |
| 92 | +/// Specifying an `n` greater than either the length of `dst` or `src` will |
| 93 | +/// likely introduce undefined behavior. |
| 94 | +#[inline] |
| 95 | +pub unsafe fn sol_memcmp(s1: &[u8], s2: &[u8], n: usize) -> i32 { |
| 96 | + #[allow(unused_mut)] |
| 97 | + let mut result = 0; |
| 98 | + |
| 99 | + #[cfg(target_os = "solana")] |
| 100 | + syscalls::sol_memcmp_(s1.as_ptr(), s2.as_ptr(), n as u64, &mut result as *mut i32); |
| 101 | + |
| 102 | + #[cfg(not(target_os = "solana"))] |
| 103 | + core::hint::black_box((s1, s2, n, result)); |
| 104 | + |
| 105 | + result |
| 106 | +} |
| 107 | + |
| 108 | +/// Like C `memset`. |
| 109 | +/// |
| 110 | +/// # Arguments |
| 111 | +/// |
| 112 | +/// - `s` - Slice to be set |
| 113 | +/// - `c` - Repeated byte to set |
| 114 | +/// - `n` - Number of bytes to set |
| 115 | +/// |
| 116 | +/// # Errors |
| 117 | +/// |
| 118 | +/// When executed within a SBF program, the memory region spanning `n` bytes |
| 119 | +/// from from the start of `s` must be mapped program memory. If not, the program |
| 120 | +/// will abort. |
| 121 | +/// |
| 122 | +/// # Safety |
| 123 | +/// |
| 124 | +/// This function does not verify that `n` is less than or equal to the length |
| 125 | +/// of the `s` slice passed to it — it will write bytes beyond the |
| 126 | +/// slice. |
| 127 | +/// |
| 128 | +/// Specifying an `n` greater than the length of `s` will likely introduce |
| 129 | +/// undefined behavior. |
| 130 | +#[inline] |
| 131 | +pub unsafe fn sol_memset(s: &mut [u8], c: u8, n: usize) { |
| 132 | + #[cfg(target_os = "solana")] |
| 133 | + syscalls::sol_memset_(s.as_mut_ptr(), c, n as u64); |
| 134 | + |
| 135 | + #[cfg(not(target_os = "solana"))] |
| 136 | + core::hint::black_box((s, c, n)); |
| 137 | +} |
0 commit comments