use crate::StorageChange;
use alloc::vec::Vec;
use alloy_primitives::U256;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "rlp", derive(alloy_rlp::RlpEncodable, alloy_rlp::RlpDecodable))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct SlotChanges {
pub slot: U256,
#[cfg_attr(feature = "serde", serde(alias = "slotChanges"))]
pub changes: Vec<StorageChange>,
}
impl SlotChanges {
#[inline]
pub const fn new(slot: U256, changes: Vec<StorageChange>) -> Self {
Self { slot, changes }
}
#[inline]
pub fn with_capacity(slot: U256, capacity: usize) -> Self {
Self { slot, changes: Vec::with_capacity(capacity) }
}
#[inline]
pub fn push(&mut self, change: StorageChange) {
self.changes.push(change)
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.changes.is_empty()
}
#[inline]
pub const fn len(&self) -> usize {
self.changes.len()
}
pub fn sort(&mut self) {
self.changes.sort_unstable_by_key(|change| change.block_access_index);
}
#[inline]
pub const fn with_slot(mut self, slot: U256) -> Self {
self.slot = slot;
self
}
#[inline]
pub fn with_change(mut self, change: StorageChange) -> Self {
self.changes.push(change);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::BlockAccessIndex;
#[test]
fn sort_orders_changes_by_block_access_index() {
let mut slot_changes = SlotChanges::new(
U256::from(1),
vec![
StorageChange::new(BlockAccessIndex::new(8), U256::from(0x80)),
StorageChange::new(BlockAccessIndex::new(2), U256::from(0x20)),
StorageChange::new(BlockAccessIndex::new(5), U256::from(0x50)),
],
);
slot_changes.sort();
assert_eq!(
slot_changes.changes.iter().map(|change| change.block_access_index).collect::<Vec<_>>(),
vec![BlockAccessIndex::new(2), BlockAccessIndex::new(5), BlockAccessIndex::new(8)]
);
}
}