use crate::types::{ArchivedEth1DataVotesDiff, Eth1DataVotesDiff};
pub fn diff_eth1_votes(base: &[u8], target: &[u8]) -> Eth1DataVotesDiff {
if target.starts_with(base) {
let appended_votes = &target[base.len()..];
Eth1DataVotesDiff::Append(appended_votes.to_vec())
} else {
Eth1DataVotesDiff::ResetAndAppend(target.to_vec())
}
}
pub fn apply_eth1_votes(base: &mut Vec<u8>, delta: &ArchivedEth1DataVotesDiff) {
match delta {
ArchivedEth1DataVotesDiff::Append(appended_votes) => {
base.extend_from_slice(appended_votes.as_slice());
}
ArchivedEth1DataVotesDiff::ResetAndAppend(replacement) => {
base.clear();
base.extend_from_slice(replacement.as_slice());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::ArchivedEth1DataVotesDiff;
fn assert_roundtrip(base: &[u8], target: &[u8]) {
let delta = diff_eth1_votes(base, target);
let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&delta).expect("test setup: serialize");
let archived = rkyv::access::<ArchivedEth1DataVotesDiff, rkyv::rancor::Error>(&bytes)
.expect("test setup: failed to access archived eth1 votes delta");
let mut reconstructed = base.to_vec();
apply_eth1_votes(&mut reconstructed, archived);
assert_eq!(reconstructed, target);
}
#[test]
fn test_diff_apply_pure_append() {
let base = b"AAAA";
let target = b"AAAABBBB";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::Append(ref v) if v == b"BBBB"));
assert_roundtrip(base, target);
}
#[test]
fn test_diff_apply_identical_lists() {
let base = b"AAAA";
let target = b"AAAA";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::Append(ref v) if v.is_empty()));
assert_roundtrip(base, target);
}
#[test]
fn test_diff_apply_empty_base() {
let base = b"";
let target = b"BBBB";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::Append(ref v) if v == b"BBBB"));
assert_roundtrip(base, target);
}
#[test]
fn test_diff_apply_complete_replacement() {
let base = b"AAAA";
let target = b"CCCC";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::ResetAndAppend(ref v) if v == b"CCCC"));
assert_roundtrip(base, target);
}
#[test]
fn test_diff_apply_target_shorter_than_base() {
let base = b"AAAABBBB";
let target = b"AA";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::ResetAndAppend(ref v) if v == b"AA"));
assert_roundtrip(base, target);
}
#[test]
fn test_diff_apply_historical_vote_modified() {
let base = b"AAAA-XXXX";
let target = b"AAAA-YYYY";
let delta = diff_eth1_votes(base, target);
assert!(matches!(delta, Eth1DataVotesDiff::ResetAndAppend(ref v) if v == b"AAAA-YYYY"));
assert_roundtrip(base, target);
}
}