@@ -115,6 +115,21 @@ impl ByteBlockWriter {
115
115
/// The util struct for reading byte blocks.
116
116
pub struct ByteBlockReader ;
117
117
118
+ /// Reads the raw part of the input byte_block at the specified offset
119
+ /// as type T.
120
+ ///
121
+ /// If `offset` + size_of::<T>() exceeds the size of the input byte_block,
122
+ /// then None will be returned.
123
+ pub fn read_type < T > ( byte_block : & [ u8 ] , offset : usize ) -> Option < & T > {
124
+ let ( next, overflow) = offset. overflowing_add ( std:: mem:: size_of :: < T > ( ) ) ;
125
+ if overflow || next > byte_block. len ( ) {
126
+ return None ;
127
+ }
128
+ let ptr = byte_block[ offset..] . as_ptr ( ) as * const T ;
129
+ debug_assert ! ( ptr as usize % std:: mem:: align_of:: <T >( ) == 0 ) ;
130
+ Some ( unsafe { & * ptr } )
131
+ }
132
+
118
133
impl ByteBlockReader {
119
134
/// Decode the input byte array using the specified format.
120
135
///
@@ -143,7 +158,7 @@ mod tests {
143
158
solana_sdk:: { hash:: Hash , stake_history:: Epoch } ,
144
159
} ;
145
160
146
- fn read_type < T > ( buffer : & [ u8 ] , offset : usize ) -> ( T , usize ) {
161
+ fn read_type_unaligned < T > ( buffer : & [ u8 ] , offset : usize ) -> ( T , usize ) {
147
162
let size = std:: mem:: size_of :: < T > ( ) ;
148
163
let ( next, overflow) = offset. overflowing_add ( size) ;
149
164
assert ! ( !overflow && next <= buffer. len( ) ) ;
@@ -170,7 +185,7 @@ mod tests {
170
185
171
186
assert_eq ! ( decoded_buffer. len( ) , mem:: size_of:: <u32 >( ) ) ;
172
187
173
- let ( value_from_buffer, next) = read_type :: < u32 > ( & decoded_buffer, 0 ) ;
188
+ let ( value_from_buffer, next) = read_type_unaligned :: < u32 > ( & decoded_buffer, 0 ) ;
174
189
assert_eq ! ( value, value_from_buffer) ;
175
190
176
191
if format != AccountBlockFormat :: AlignedRaw {
@@ -250,25 +265,29 @@ mod tests {
250
265
) ;
251
266
252
267
// verify meta1 and its data
253
- let ( meta1_from_buffer, next1) = read_type :: < TestMetaStruct > ( & decoded_buffer, 0 ) ;
268
+ let ( meta1_from_buffer, next1) = read_type_unaligned :: < TestMetaStruct > ( & decoded_buffer, 0 ) ;
254
269
assert_eq ! ( test_metas[ 0 ] , meta1_from_buffer) ;
255
270
assert_eq ! (
256
271
test_data1,
257
272
decoded_buffer[ next1..] [ ..meta1_from_buffer. data_len]
258
273
) ;
259
274
260
275
// verify meta2 and its data
261
- let ( meta2_from_buffer, next2) =
262
- read_type :: < TestMetaStruct > ( & decoded_buffer, next1 + meta1_from_buffer. data_len ) ;
276
+ let ( meta2_from_buffer, next2) = read_type_unaligned :: < TestMetaStruct > (
277
+ & decoded_buffer,
278
+ next1 + meta1_from_buffer. data_len ,
279
+ ) ;
263
280
assert_eq ! ( test_metas[ 1 ] , meta2_from_buffer) ;
264
281
assert_eq ! (
265
282
test_data2,
266
283
decoded_buffer[ next2..] [ ..meta2_from_buffer. data_len]
267
284
) ;
268
285
269
286
// verify meta3 and its data
270
- let ( meta3_from_buffer, next3) =
271
- read_type :: < TestMetaStruct > ( & decoded_buffer, next2 + meta2_from_buffer. data_len ) ;
287
+ let ( meta3_from_buffer, next3) = read_type_unaligned :: < TestMetaStruct > (
288
+ & decoded_buffer,
289
+ next2 + meta2_from_buffer. data_len ,
290
+ ) ;
272
291
assert_eq ! ( test_metas[ 2 ] , meta3_from_buffer) ;
273
292
assert_eq ! (
274
293
test_data3,
@@ -337,23 +356,23 @@ mod tests {
337
356
let mut offset = 0 ;
338
357
for opt_fields in & opt_fields_vec {
339
358
if let Some ( expected_rent_epoch) = opt_fields. rent_epoch {
340
- let ( rent_epoch, next ) = read_type :: < Epoch > ( & decoded_buffer, offset) ;
341
- assert_eq ! ( rent_epoch, expected_rent_epoch) ;
359
+ let rent_epoch = read_type :: < Epoch > ( & decoded_buffer, offset) . unwrap ( ) ;
360
+ assert_eq ! ( * rent_epoch, expected_rent_epoch) ;
342
361
verified_count += 1 ;
343
- offset = next ;
362
+ offset += std :: mem :: size_of :: < Epoch > ( ) ;
344
363
}
345
364
if let Some ( expected_hash) = opt_fields. account_hash {
346
- let ( hash, next ) = read_type :: < Hash > ( & decoded_buffer, offset) ;
347
- assert_eq ! ( hash, expected_hash) ;
365
+ let hash = read_type :: < Hash > ( & decoded_buffer, offset) . unwrap ( ) ;
366
+ assert_eq ! ( hash, & expected_hash) ;
348
367
verified_count += 1 ;
349
- offset = next ;
368
+ offset += std :: mem :: size_of :: < Hash > ( ) ;
350
369
}
351
370
if let Some ( expected_write_version) = opt_fields. write_version {
352
- let ( write_version, next ) =
353
- read_type :: < StoredMetaWriteVersion > ( & decoded_buffer, offset) ;
354
- assert_eq ! ( write_version, expected_write_version) ;
371
+ let write_version =
372
+ read_type :: < StoredMetaWriteVersion > ( & decoded_buffer, offset) . unwrap ( ) ;
373
+ assert_eq ! ( * write_version, expected_write_version) ;
355
374
verified_count += 1 ;
356
- offset = next ;
375
+ offset += std :: mem :: size_of :: < StoredMetaWriteVersion > ( ) ;
357
376
}
358
377
}
359
378
0 commit comments