solana_stable_layout/
stable_vec.rs1use std::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
4
5#[repr(C)]
26pub struct StableVec<T> {
27 pub ptr: NonNull<T>,
28 pub cap: usize,
29 pub len: usize,
30 _marker: PhantomData<T>,
31}
32
33impl<T> StableVec<T> {
36 #[inline]
37 pub fn as_ptr(&self) -> *const T {
38 self.ptr.as_ptr()
39 }
40
41 #[inline]
42 pub fn as_mut_ptr(&mut self) -> *mut T {
43 self.ptr.as_ptr()
44 }
45
46 #[inline]
47 pub fn len(&self) -> usize {
48 self.len
49 }
50
51 #[inline]
52 pub fn is_empty(&self) -> bool {
53 self.len == 0
54 }
55}
56
57impl<T> AsRef<[T]> for StableVec<T> {
58 fn as_ref(&self) -> &[T] {
59 self
60 }
61}
62
63impl<T> AsMut<[T]> for StableVec<T> {
64 fn as_mut(&mut self) -> &mut [T] {
65 self
66 }
67}
68
69impl<T> std::ops::Deref for StableVec<T> {
70 type Target = [T];
71
72 #[inline]
73 fn deref(&self) -> &[T] {
74 unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len) }
75 }
76}
77
78impl<T> std::ops::DerefMut for StableVec<T> {
79 #[inline]
80 fn deref_mut(&mut self) -> &mut [T] {
81 unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
82 }
83}
84
85impl<T: std::fmt::Debug> std::fmt::Debug for StableVec<T> {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 std::fmt::Debug::fmt(&**self, f)
88 }
89}
90
91macro_rules! impl_partial_eq {
92 ([$($vars:tt)*] $lhs:ty, $rhs:ty) => {
93 impl<T, U, $($vars)*> PartialEq<$rhs> for $lhs
94 where
95 T: PartialEq<U>,
96 {
97 #[inline]
98 fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] }
99 }
100 }
101}
102impl_partial_eq! { [] StableVec<T>, StableVec<U> }
103impl_partial_eq! { [] StableVec<T>, Vec<U> }
104impl_partial_eq! { [] Vec<T>, StableVec<U> }
105impl_partial_eq! { [] StableVec<T>, &[U] }
106impl_partial_eq! { [] StableVec<T>, &mut [U] }
107impl_partial_eq! { [] &[T], StableVec<U> }
108impl_partial_eq! { [] &mut [T], StableVec<U> }
109impl_partial_eq! { [] StableVec<T>, [U] }
110impl_partial_eq! { [] [T], StableVec<U> }
111impl_partial_eq! { [const N: usize] StableVec<T>, [U; N] }
112impl_partial_eq! { [const N: usize] StableVec<T>, &[U; N] }
113
114impl<T> From<Vec<T>> for StableVec<T> {
115 fn from(other: Vec<T>) -> Self {
116 let mut other = ManuallyDrop::new(other);
122 Self {
123 ptr: unsafe { NonNull::new_unchecked(other.as_mut_ptr()) },
125 cap: other.capacity(),
126 len: other.len(),
127 _marker: PhantomData,
128 }
129 }
130}
131
132impl<T> From<StableVec<T>> for Vec<T> {
133 fn from(other: StableVec<T>) -> Self {
134 let other = ManuallyDrop::new(other);
137 unsafe { Vec::from_raw_parts(other.ptr.as_ptr(), other.len, other.cap) }
140 }
141}
142
143impl<T> Drop for StableVec<T> {
144 fn drop(&mut self) {
145 let _vec = unsafe { Vec::from_raw_parts(self.ptr.as_ptr(), self.len, self.cap) };
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use {
157 super::*,
158 memoffset::offset_of,
159 std::mem::{align_of, size_of},
160 };
161
162 #[test]
163 fn test_memory_layout() {
164 assert_eq!(offset_of!(StableVec<i32>, ptr), 0);
165 assert_eq!(offset_of!(StableVec<i32>, cap), 8);
166 assert_eq!(offset_of!(StableVec<i32>, len), 16);
167 assert_eq!(align_of::<StableVec<i32>>(), 8);
168 assert_eq!(size_of::<StableVec<i32>>(), 8 + 8 + 8);
169
170 let vec = {
172 let mut vec = Vec::with_capacity(3);
173 vec.push(11);
174 vec.push(22);
175 vec
176 };
177 let vec = StableVec::from(vec);
178
179 let addr_vec = &vec as *const _ as usize;
180 let addr_ptr = addr_vec;
181 let addr_cap = addr_vec + 8;
182 let addr_len = addr_vec + 16;
183 assert_eq!(unsafe { *(addr_cap as *const usize) }, 3);
184 assert_eq!(unsafe { *(addr_len as *const usize) }, 2);
185
186 let ptr_data = addr_ptr as *const &[i32; 2];
187 assert_eq!(unsafe { *ptr_data }, &[11, 22]);
188 }
189}