cfx_storage/impls/merkle_patricia_trie/
maybe_in_place_byte_array.rs1use std::{
6 marker::PhantomData,
7 ptr::{null_mut, NonNull},
8 slice,
9};
10
11pub union MaybeInPlaceByteArray {
18 pub in_place: [u8; Self::MAX_INPLACE_SIZE],
19 pub ptr: *mut u8,
21}
22
23impl MaybeInPlaceByteArray {
24 pub const MAX_INPLACE_SIZE: usize = 8;
25}
26
27#[test]
28fn test_maybe_inplace_byte_array_size_is_8_bytes() {
29 assert_eq!(
30 std::mem::size_of::<MaybeInPlaceByteArray>(),
31 MaybeInPlaceByteArray::MAX_INPLACE_SIZE
32 );
33}
34impl Default for MaybeInPlaceByteArray {
35 fn default() -> Self {
36 Self {
37 in_place: Default::default(),
38 }
39 }
40}
41
42#[allow(drop_bounds)]
45pub trait MaybeInPlaceByteArrayMemoryManagerTrait: Drop {
46 unsafe fn drop_value(&mut self) {
48 let size = self.get_size();
49 if size > MaybeInPlaceByteArray::MAX_INPLACE_SIZE {
50 self.get_in_place_byte_array_mut().ptr_into_vec(size);
51 }
52 }
53
54 fn get_size(&self) -> usize;
55 fn set_size(&mut self, size: usize);
56 fn get_in_place_byte_array(&self) -> &MaybeInPlaceByteArray;
57 fn get_in_place_byte_array_mut(&mut self) -> &mut MaybeInPlaceByteArray;
58
59 unsafe fn move_byte_array_dest_unchecked(
61 &mut self, free_dest: &mut MaybeInPlaceByteArray,
62 ) {
63 self.set_size(0);
64
65 std::ptr::copy_nonoverlapping(
66 self.get_in_place_byte_array(),
67 free_dest,
68 1,
69 );
70 }
71
72 fn move_to<T: MaybeInPlaceByteArrayMemoryManagerTrait>(
73 &mut self, dest: &mut T,
74 ) {
75 let size = self.get_size();
76
77 unsafe {
79 dest.drop_value();
80 dest.set_size(size);
81 }
82 if size != 0 {
83 unsafe {
85 self.move_byte_array_dest_unchecked(
86 dest.get_in_place_byte_array_mut(),
87 );
88 }
89 }
90 }
91}
92
93#[derive(Default, Clone)]
94pub struct FieldsOffsetMaybeInPlaceByteArrayMemoryManager<
95 SizeFieldType,
96 SizeFieldGetterSetter: SizeFieldConverterTrait<SizeFieldType>,
97 ByteArrayOffsetAccessor: ParallelFieldOffsetAccessor<Self, MaybeInPlaceByteArray>,
98 SizeFieldOffsetAccessor: ParallelFieldOffsetAccessor<Self, SizeFieldType>,
99> {
100 _marker_size_type: PhantomData<SizeFieldType>,
101 _marker_size_field_getter_setter: PhantomData<SizeFieldGetterSetter>,
102 _marker_byte_array_accessor: PhantomData<ByteArrayOffsetAccessor>,
103 _marker_size_field_accessor: PhantomData<SizeFieldOffsetAccessor>,
104}
105
106impl<
107 SizeFieldType,
108 SizeFieldGetterSetter: SizeFieldConverterTrait<SizeFieldType>,
109 ByteArrayOffsetAccessor: ParallelFieldOffsetAccessor<Self, MaybeInPlaceByteArray>,
110 SizeFieldOffsetAccessor: ParallelFieldOffsetAccessor<Self, SizeFieldType>,
111 > Drop
112 for FieldsOffsetMaybeInPlaceByteArrayMemoryManager<
113 SizeFieldType,
114 SizeFieldGetterSetter,
115 ByteArrayOffsetAccessor,
116 SizeFieldOffsetAccessor,
117 >
118{
119 fn drop(&mut self) {
120 unsafe {
122 self.drop_value();
123 }
124 }
125}
126
127impl MaybeInPlaceByteArray {
128 pub unsafe fn ptr_into_vec(&mut self, size: usize) -> Vec<u8> {
130 debug_assert!(!self.ptr.is_null() || size == 0);
131 let ptr = if self.ptr.is_null() {
132 NonNull::dangling().as_ptr()
133 } else {
134 self.ptr
135 };
136 let vec = Vec::from_raw_parts(ptr, size, size);
137 self.ptr = null_mut();
138 vec
139 }
140
141 unsafe fn ptr_slice(&self, size: usize) -> &[u8] {
142 debug_assert!(!self.ptr.is_null() || size == 0);
143 slice::from_raw_parts(
144 if self.ptr.is_null() {
145 NonNull::dangling().as_ptr()
146 } else {
147 self.ptr
148 },
149 size,
150 )
151 }
152
153 unsafe fn ptr_slice_mut(&mut self, size: usize) -> &mut [u8] {
154 debug_assert!(!self.ptr.is_null() || size == 0);
155 slice::from_raw_parts_mut(
156 if self.ptr.is_null() {
157 NonNull::dangling().as_ptr()
158 } else {
159 self.ptr
160 },
161 size,
162 )
163 }
164
165 pub fn get_slice_mut(&mut self, size: usize) -> &mut [u8] {
166 let is_ptr = size > Self::MAX_INPLACE_SIZE;
167 unsafe {
168 if is_ptr {
169 self.ptr_slice_mut(size)
170 } else {
171 &mut self.in_place[0..size]
172 }
173 }
174 }
175
176 pub fn get_slice(&self, size: usize) -> &[u8] {
177 let is_ptr = size > Self::MAX_INPLACE_SIZE;
178 unsafe {
179 if is_ptr {
180 self.ptr_slice(size)
181 } else {
182 &self.in_place[0..size]
183 }
184 }
185 }
186
187 pub fn into_boxed_slice(&mut self, size: usize) -> Box<[u8]> {
188 let is_ptr = size > Self::MAX_INPLACE_SIZE;
189 unsafe {
190 if is_ptr {
191 self.ptr_into_vec(size)
192 } else {
193 Vec::from(&self.in_place[0..size])
194 }
195 }
196 .into_boxed_slice()
197 }
198
199 pub fn new(mut value: Box<[u8]>, size: usize) -> Self {
200 if size > Self::MAX_INPLACE_SIZE {
201 let ptr = value.as_mut_ptr();
202 let _ = Box::into_raw(value);
203 Self { ptr }
204 } else {
205 let mut in_place: [u8; Self::MAX_INPLACE_SIZE] = Default::default();
206 in_place[0..size].copy_from_slice(&*value);
207 Self { in_place }
208 }
209 }
210
211 pub fn new_zeroed(size: usize) -> Self {
212 Self::new(vec![0u8; size].into_boxed_slice(), size)
213 }
214
215 pub fn copy_from(value: &[u8], size: usize) -> Self {
216 if size > Self::MAX_INPLACE_SIZE {
217 let mut owned_copy = Box::<[u8]>::from(value);
218 let ptr = owned_copy.as_mut_ptr();
219 let _ = Box::into_raw(owned_copy);
220 Self { ptr }
221 } else {
222 let mut x: Self = Self {
223 in_place: Default::default(),
224 };
225 unsafe {
226 x.in_place[0..size].copy_from_slice(value);
227 }
228 x
229 }
230 }
231
232 pub fn clone(&self, size: usize) -> Self {
233 if size > Self::MAX_INPLACE_SIZE {
234 Self::copy_from(unsafe { self.ptr_slice(size) }, size)
236 } else {
237 Self {
238 in_place: unsafe { self.in_place }.clone(),
239 }
240 }
241 }
242}
243
244pub trait ParallelFieldOffsetAccessor<FromFieldType, TargetFieldType> {
245 fn get(m: &FromFieldType) -> &TargetFieldType;
246 fn get_mut(m: &mut FromFieldType) -> &mut TargetFieldType;
247}
248
249pub trait SizeFieldConverterTrait<SizeFieldType> {
250 fn max_size() -> usize;
251 fn is_size_over_limit(size: usize) -> bool;
252 fn get(size_field: &SizeFieldType) -> usize;
253 fn set(size_field: &mut SizeFieldType, size: usize);
254}
255
256#[derive(Default)]
257pub struct TrivialSizeFieldConverterU16 {}
258
259impl SizeFieldConverterTrait<u16> for TrivialSizeFieldConverterU16 {
260 fn max_size() -> usize { std::u16::MAX as usize }
261
262 fn is_size_over_limit(size: usize) -> bool { size > std::u16::MAX as usize }
263
264 fn get(size_field: &u16) -> usize { (*size_field) as usize }
265
266 fn set(size_field: &mut u16, size: usize) { *size_field = size as u16; }
267}
268
269impl<
270 SizeFieldType,
271 SizeFieldGetterSetter: SizeFieldConverterTrait<SizeFieldType>,
272 ByteArrayOffsetAccessor: ParallelFieldOffsetAccessor<Self, MaybeInPlaceByteArray>,
273 SizeFieldOffsetAccessor: ParallelFieldOffsetAccessor<Self, SizeFieldType>,
274 > MaybeInPlaceByteArrayMemoryManagerTrait
275 for FieldsOffsetMaybeInPlaceByteArrayMemoryManager<
276 SizeFieldType,
277 SizeFieldGetterSetter,
278 ByteArrayOffsetAccessor,
279 SizeFieldOffsetAccessor,
280 >
281{
282 fn get_size(&self) -> usize {
283 SizeFieldGetterSetter::get(SizeFieldOffsetAccessor::get(self))
284 }
285
286 fn set_size(&mut self, size: usize) {
287 SizeFieldGetterSetter::set(
288 SizeFieldOffsetAccessor::get_mut(self),
289 size,
290 );
291 }
292
293 fn get_in_place_byte_array(&self) -> &MaybeInPlaceByteArray {
294 ByteArrayOffsetAccessor::get(self)
295 }
296
297 fn get_in_place_byte_array_mut(&mut self) -> &mut MaybeInPlaceByteArray {
298 ByteArrayOffsetAccessor::get_mut(self)
299 }
300}