[TieredStorage] byte_block::read_type (#32295)
#### Summary of Changes This PR adds byte_block::read_type(), an util function that reads the raw part of the input byte block at the specified offset as type T. This function will be later used by the hot storage. #### Test Plan Modified existing unit tests to use byte_block::read_type() when the input byte block is properly aligned.
This commit is contained in:
parent
5624aaa1e5
commit
4cfdb374ae
|
@ -115,6 +115,21 @@ impl ByteBlockWriter {
|
||||||
/// The util struct for reading byte blocks.
|
/// The util struct for reading byte blocks.
|
||||||
pub struct ByteBlockReader;
|
pub struct ByteBlockReader;
|
||||||
|
|
||||||
|
/// Reads the raw part of the input byte_block at the specified offset
|
||||||
|
/// as type T.
|
||||||
|
///
|
||||||
|
/// If `offset` + size_of::<T>() exceeds the size of the input byte_block,
|
||||||
|
/// then None will be returned.
|
||||||
|
pub fn read_type<T>(byte_block: &[u8], offset: usize) -> Option<&T> {
|
||||||
|
let (next, overflow) = offset.overflowing_add(std::mem::size_of::<T>());
|
||||||
|
if overflow || next > byte_block.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let ptr = byte_block[offset..].as_ptr() as *const T;
|
||||||
|
debug_assert!(ptr as usize % std::mem::align_of::<T>() == 0);
|
||||||
|
Some(unsafe { &*ptr })
|
||||||
|
}
|
||||||
|
|
||||||
impl ByteBlockReader {
|
impl ByteBlockReader {
|
||||||
/// Decode the input byte array using the specified format.
|
/// Decode the input byte array using the specified format.
|
||||||
///
|
///
|
||||||
|
@ -143,7 +158,7 @@ mod tests {
|
||||||
solana_sdk::{hash::Hash, stake_history::Epoch},
|
solana_sdk::{hash::Hash, stake_history::Epoch},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn read_type<T>(buffer: &[u8], offset: usize) -> (T, usize) {
|
fn read_type_unaligned<T>(buffer: &[u8], offset: usize) -> (T, usize) {
|
||||||
let size = std::mem::size_of::<T>();
|
let size = std::mem::size_of::<T>();
|
||||||
let (next, overflow) = offset.overflowing_add(size);
|
let (next, overflow) = offset.overflowing_add(size);
|
||||||
assert!(!overflow && next <= buffer.len());
|
assert!(!overflow && next <= buffer.len());
|
||||||
|
@ -170,7 +185,7 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(decoded_buffer.len(), mem::size_of::<u32>());
|
assert_eq!(decoded_buffer.len(), mem::size_of::<u32>());
|
||||||
|
|
||||||
let (value_from_buffer, next) = read_type::<u32>(&decoded_buffer, 0);
|
let (value_from_buffer, next) = read_type_unaligned::<u32>(&decoded_buffer, 0);
|
||||||
assert_eq!(value, value_from_buffer);
|
assert_eq!(value, value_from_buffer);
|
||||||
|
|
||||||
if format != AccountBlockFormat::AlignedRaw {
|
if format != AccountBlockFormat::AlignedRaw {
|
||||||
|
@ -250,7 +265,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// verify meta1 and its data
|
// verify meta1 and its data
|
||||||
let (meta1_from_buffer, next1) = read_type::<TestMetaStruct>(&decoded_buffer, 0);
|
let (meta1_from_buffer, next1) = read_type_unaligned::<TestMetaStruct>(&decoded_buffer, 0);
|
||||||
assert_eq!(test_metas[0], meta1_from_buffer);
|
assert_eq!(test_metas[0], meta1_from_buffer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_data1,
|
test_data1,
|
||||||
|
@ -258,8 +273,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// verify meta2 and its data
|
// verify meta2 and its data
|
||||||
let (meta2_from_buffer, next2) =
|
let (meta2_from_buffer, next2) = read_type_unaligned::<TestMetaStruct>(
|
||||||
read_type::<TestMetaStruct>(&decoded_buffer, next1 + meta1_from_buffer.data_len);
|
&decoded_buffer,
|
||||||
|
next1 + meta1_from_buffer.data_len,
|
||||||
|
);
|
||||||
assert_eq!(test_metas[1], meta2_from_buffer);
|
assert_eq!(test_metas[1], meta2_from_buffer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_data2,
|
test_data2,
|
||||||
|
@ -267,8 +284,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// verify meta3 and its data
|
// verify meta3 and its data
|
||||||
let (meta3_from_buffer, next3) =
|
let (meta3_from_buffer, next3) = read_type_unaligned::<TestMetaStruct>(
|
||||||
read_type::<TestMetaStruct>(&decoded_buffer, next2 + meta2_from_buffer.data_len);
|
&decoded_buffer,
|
||||||
|
next2 + meta2_from_buffer.data_len,
|
||||||
|
);
|
||||||
assert_eq!(test_metas[2], meta3_from_buffer);
|
assert_eq!(test_metas[2], meta3_from_buffer);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_data3,
|
test_data3,
|
||||||
|
@ -337,23 +356,23 @@ mod tests {
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for opt_fields in &opt_fields_vec {
|
for opt_fields in &opt_fields_vec {
|
||||||
if let Some(expected_rent_epoch) = opt_fields.rent_epoch {
|
if let Some(expected_rent_epoch) = opt_fields.rent_epoch {
|
||||||
let (rent_epoch, next) = read_type::<Epoch>(&decoded_buffer, offset);
|
let rent_epoch = read_type::<Epoch>(&decoded_buffer, offset).unwrap();
|
||||||
assert_eq!(rent_epoch, expected_rent_epoch);
|
assert_eq!(*rent_epoch, expected_rent_epoch);
|
||||||
verified_count += 1;
|
verified_count += 1;
|
||||||
offset = next;
|
offset += std::mem::size_of::<Epoch>();
|
||||||
}
|
}
|
||||||
if let Some(expected_hash) = opt_fields.account_hash {
|
if let Some(expected_hash) = opt_fields.account_hash {
|
||||||
let (hash, next) = read_type::<Hash>(&decoded_buffer, offset);
|
let hash = read_type::<Hash>(&decoded_buffer, offset).unwrap();
|
||||||
assert_eq!(hash, expected_hash);
|
assert_eq!(hash, &expected_hash);
|
||||||
verified_count += 1;
|
verified_count += 1;
|
||||||
offset = next;
|
offset += std::mem::size_of::<Hash>();
|
||||||
}
|
}
|
||||||
if let Some(expected_write_version) = opt_fields.write_version {
|
if let Some(expected_write_version) = opt_fields.write_version {
|
||||||
let (write_version, next) =
|
let write_version =
|
||||||
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset);
|
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset).unwrap();
|
||||||
assert_eq!(write_version, expected_write_version);
|
assert_eq!(*write_version, expected_write_version);
|
||||||
verified_count += 1;
|
verified_count += 1;
|
||||||
offset = next;
|
offset += std::mem::size_of::<StoredMetaWriteVersion>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue