use trait to simplify and consolidate cumulative code (#17852)

This commit is contained in:
Jeff Washington (jwash) 2021-06-14 08:43:59 -05:00 committed by GitHub
parent 32742df1b4
commit 2dc6969858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 23 deletions

View File

@ -108,6 +108,22 @@ impl CumulativeOffset {
}
}
pub trait ExtractSliceFromRawData<'b, T: 'b> {
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T];
}
impl<'b, T: 'b> ExtractSliceFromRawData<'b, T> for Vec<Vec<T>> {
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T] {
&self[offset.index[0]][start..]
}
}
impl<'b, T: 'b> ExtractSliceFromRawData<'b, T> for Vec<Vec<Vec<T>>> {
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T] {
&self[offset.index[0]][offset.index[1]][start..]
}
}
// Allow retrieving &[start..end] from a logical src: Vec<T>, where src is really Vec<Vec<T>> (or later Vec<Vec<Vec<T>>>)
// This model prevents callers from having to flatten which saves both working memory and time.
#[derive(Default, Debug)]
@ -163,32 +179,28 @@ impl CumulativeOffsets {
}
}
fn find(&self, start: usize) -> (usize, &CumulativeOffset) {
fn find_index(&self, start: usize) -> usize {
assert!(!self.cumulative_offsets.is_empty());
let index = match self.cumulative_offsets[..]
.binary_search_by(|index| index.start_offset.cmp(&start))
{
match self.cumulative_offsets[..].binary_search_by(|index| index.start_offset.cmp(&start)) {
Ok(index) => index,
Err(index) => index - 1, // we would insert at index so we are before the item at index
};
}
}
fn find(&self, start: usize) -> (usize, &CumulativeOffset) {
let index = self.find_index(start);
let index = &self.cumulative_offsets[index];
let start = start - index.start_offset;
(start, index)
}
// return the biggest slice possible that starts at 'start'
pub fn get_slice<'a, T>(&self, raw: &'a [Vec<T>], start: usize) -> &'a [T] {
pub fn get_slice<'a, 'b, T, U>(&'a self, raw: &'b U, start: usize) -> &'b [T]
where
U: ExtractSliceFromRawData<'b, T> + 'b,
{
let (start, index) = self.find(start);
const DIMENSION: usize = 0;
&raw[index.index[DIMENSION]][start..]
}
// return the biggest slice possible that starts at 'start'
pub fn get_slice_2d<'a, T>(&self, raw: &'a [Vec<Vec<T>>], start: usize) -> &'a [T] {
let (start, index) = self.find(start);
const DIMENSION_0: usize = 0;
const DIMENSION_1: usize = 1;
&raw[index.index[DIMENSION_0]][index.index[DIMENSION_1]][start..]
raw.extract(index, start)
}
}
@ -751,7 +763,7 @@ impl AccountsHash {
// move tail hashes that don't evenly hash into a 1d vector for next time
let mut i = hash_total - left_over_hashes;
while i < hash_total {
let data = cumulative.get_slice_2d(&hashes, i);
let data = cumulative.get_slice(&hashes, i);
next_pass.remaining_unhashed.extend(data);
i += data.len();
}
@ -769,7 +781,7 @@ impl AccountsHash {
hash_total, // note this does not include the ones that didn't divide evenly, unless we're in the last iteration
MERKLE_FANOUT,
Some(TARGET_FANOUT_LEVEL),
|start| cumulative.get_slice_2d(&hashes, start),
|start| cumulative.get_slice(&hashes, start),
Some(TARGET_FANOUT_LEVEL),
)
.1;
@ -1636,7 +1648,7 @@ pub mod tests {
#[test]
fn test_accountsdb_cumulative_offsets2_d() {
let input = vec![vec![vec![0, 1], vec![], vec![2, 3, 4], vec![]]];
let input: Vec<Vec<Vec<u64>>> = vec![vec![vec![0, 1], vec![], vec![2, 3, 4], vec![]]];
let cumulative = CumulativeOffsets::from_raw_2d(&input);
let src: Vec<_> = input
@ -1661,7 +1673,7 @@ pub mod tests {
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
for start in 0..len {
let slice = cumulative.get_slice_2d(&input, start);
let slice: &[u64] = cumulative.get_slice(&input, start);
let len = slice.len();
assert!(len > 0);
assert_eq!(&src[start..(start + len)], slice);
@ -1690,7 +1702,7 @@ pub mod tests {
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
for start in 0..len {
let slice = cumulative.get_slice_2d(&input, start);
let slice: &[u64] = cumulative.get_slice(&input, start);
let len = slice.len();
assert!(len > 0);
assert_eq!(&src[start..(start + len)], slice);
@ -1731,7 +1743,7 @@ pub mod tests {
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
for start in 0..len {
let slice = cumulative.get_slice_2d(&input, start);
let slice: &[u64] = cumulative.get_slice(&input, start);
let len = slice.len();
assert!(len > 0);
assert_eq!(&src[start..(start + len)], slice);
@ -1903,7 +1915,7 @@ pub mod tests {
];
let offsets = CumulativeOffsets::from_raw_2d(&src);
let get_slice = |start: usize| -> &[Hash] { offsets.get_slice_2d(&src, start) };
let get_slice = |start: usize| -> &[Hash] { offsets.get_slice(&src, start) };
let result2 = AccountsHash::compute_merkle_root_from_slices(
offsets.total_count,
fanout,