1use std::ops::Range;
2
3use alloy_eips::eip4895::Withdrawals;
4use alloy_primitives::TxNumber;
5use reth_codecs::{add_arbitrary_tests, Compact};
6use serde::{Deserialize, Serialize};
7
8pub type NumTransactions = u64;
10
11#[derive(Debug, Default, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Compact)]
16#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
17#[add_arbitrary_tests(compact)]
18pub struct StoredBlockBodyIndices {
19 pub first_tx_num: TxNumber,
24 pub tx_count: NumTransactions,
29}
30
31impl StoredBlockBodyIndices {
32 pub const fn tx_num_range(&self) -> Range<TxNumber> {
34 self.first_tx_num..self.first_tx_num + self.tx_count
35 }
36
37 pub const fn last_tx_num(&self) -> TxNumber {
41 self.first_tx_num.saturating_add(self.tx_count).saturating_sub(1)
42 }
43
44 pub const fn first_tx_num(&self) -> TxNumber {
49 self.first_tx_num
50 }
51
52 pub const fn next_tx_num(&self) -> TxNumber {
54 self.first_tx_num + self.tx_count
55 }
56
57 pub const fn is_empty(&self) -> bool {
59 self.tx_count == 0
60 }
61
62 pub const fn tx_count(&self) -> NumTransactions {
66 self.tx_count
67 }
68}
69
70#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, Compact)]
72#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
73#[add_arbitrary_tests(compact)]
74pub struct StoredBlockWithdrawals {
75 pub withdrawals: Withdrawals,
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::StoredBlockBodyIndices;
82
83 #[test]
84 fn block_indices() {
85 let first_tx_num = 10;
86 let tx_count = 6;
87 let block_indices = StoredBlockBodyIndices { first_tx_num, tx_count };
88
89 assert_eq!(block_indices.first_tx_num(), first_tx_num);
90 assert_eq!(block_indices.last_tx_num(), first_tx_num + tx_count - 1);
91 assert_eq!(block_indices.next_tx_num(), first_tx_num + tx_count);
92 assert_eq!(block_indices.tx_count(), tx_count);
93 assert_eq!(block_indices.tx_num_range(), first_tx_num..first_tx_num + tx_count);
94 }
95}