1use core::fmt::Display;
4
5use crate::{
6 execute::{BatchExecutor, BlockExecutorProvider, Executor},
7 system_calls::OnStateHook,
8};
9use alloc::boxed::Box;
10use alloy_primitives::BlockNumber;
11use reth_prune_types::PruneModes;
12use reth_storage_errors::provider::ProviderError;
13use revm_primitives::db::Database;
14
15pub use futures_util::future::Either;
17use revm::State;
18
19impl<A, B> BlockExecutorProvider for Either<A, B>
20where
21 A: BlockExecutorProvider,
22 B: BlockExecutorProvider<Primitives = A::Primitives>,
23{
24 type Primitives = A::Primitives;
25
26 type Executor<DB: Database<Error: Into<ProviderError> + Display>> =
27 Either<A::Executor<DB>, B::Executor<DB>>;
28
29 type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> =
30 Either<A::BatchExecutor<DB>, B::BatchExecutor<DB>>;
31
32 fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
33 where
34 DB: Database<Error: Into<ProviderError> + Display>,
35 {
36 match self {
37 Self::Left(a) => Either::Left(a.executor(db)),
38 Self::Right(b) => Either::Right(b.executor(db)),
39 }
40 }
41
42 fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
43 where
44 DB: Database<Error: Into<ProviderError> + Display>,
45 {
46 match self {
47 Self::Left(a) => Either::Left(a.batch_executor(db)),
48 Self::Right(b) => Either::Right(b.batch_executor(db)),
49 }
50 }
51}
52
53impl<A, B, DB> Executor<DB> for Either<A, B>
54where
55 A: Executor<DB>,
56 B: for<'a> Executor<DB, Input<'a> = A::Input<'a>, Output = A::Output, Error = A::Error>,
57 DB: Database<Error: Into<ProviderError> + Display>,
58{
59 type Input<'a> = A::Input<'a>;
60 type Output = A::Output;
61 type Error = A::Error;
62
63 fn init(&mut self, tx_env_overrides: Box<dyn crate::TxEnvOverrides>) {
64 match self {
65 Self::Left(a) => a.init(tx_env_overrides),
66 Self::Right(b) => b.init(tx_env_overrides),
67 }
68 }
69
70 fn execute(self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
71 match self {
72 Self::Left(a) => a.execute(input),
73 Self::Right(b) => b.execute(input),
74 }
75 }
76
77 fn execute_with_state_closure<F>(
78 self,
79 input: Self::Input<'_>,
80 witness: F,
81 ) -> Result<Self::Output, Self::Error>
82 where
83 F: FnMut(&State<DB>),
84 {
85 match self {
86 Self::Left(a) => a.execute_with_state_closure(input, witness),
87 Self::Right(b) => b.execute_with_state_closure(input, witness),
88 }
89 }
90
91 fn execute_with_state_hook<F>(
92 self,
93 input: Self::Input<'_>,
94 state_hook: F,
95 ) -> Result<Self::Output, Self::Error>
96 where
97 F: OnStateHook + 'static,
98 {
99 match self {
100 Self::Left(a) => a.execute_with_state_hook(input, state_hook),
101 Self::Right(b) => b.execute_with_state_hook(input, state_hook),
102 }
103 }
104}
105
106impl<A, B, DB> BatchExecutor<DB> for Either<A, B>
107where
108 A: BatchExecutor<DB>,
109 B: for<'a> BatchExecutor<DB, Input<'a> = A::Input<'a>, Output = A::Output, Error = A::Error>,
110 DB: Database<Error: Into<ProviderError> + Display>,
111{
112 type Input<'a> = A::Input<'a>;
113 type Output = A::Output;
114 type Error = A::Error;
115
116 fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> {
117 match self {
118 Self::Left(a) => a.execute_and_verify_one(input),
119 Self::Right(b) => b.execute_and_verify_one(input),
120 }
121 }
122
123 fn finalize(self) -> Self::Output {
124 match self {
125 Self::Left(a) => a.finalize(),
126 Self::Right(b) => b.finalize(),
127 }
128 }
129
130 fn set_tip(&mut self, tip: BlockNumber) {
131 match self {
132 Self::Left(a) => a.set_tip(tip),
133 Self::Right(b) => b.set_tip(tip),
134 }
135 }
136
137 fn set_prune_modes(&mut self, prune_modes: PruneModes) {
138 match self {
139 Self::Left(a) => a.set_prune_modes(prune_modes),
140 Self::Right(b) => b.set_prune_modes(prune_modes),
141 }
142 }
143
144 fn size_hint(&self) -> Option<usize> {
145 match self {
146 Self::Left(a) => a.size_hint(),
147 Self::Right(b) => b.size_hint(),
148 }
149 }
150}