iptr_edge_analyzer/control_flow_handler/
combined.rs1use crate::HandleControlFlow;
4
5use perfect_derive::perfect_derive;
6use thiserror::Error;
7
8pub struct CombinedControlFlowHandler<H1, H2>
10where
11 H1: HandleControlFlow,
12 H2: HandleControlFlow,
13{
14 handler1: H1,
15 handler2: H2,
16}
17
18impl<H1, H2> CombinedControlFlowHandler<H1, H2>
19where
20 H1: HandleControlFlow,
21 H2: HandleControlFlow,
22{
23 #[must_use]
25 pub fn new(handler1: H1, handler2: H2) -> Self {
26 Self { handler1, handler2 }
27 }
28
29 pub fn into_inner(self) -> (H1, H2) {
31 (self.handler1, self.handler2)
32 }
33
34 pub fn handler1(&self) -> &H1 {
36 &self.handler1
37 }
38
39 pub fn handler1_mut(&mut self) -> &mut H1 {
41 &mut self.handler1
42 }
43
44 pub fn handler2(&self) -> &H2 {
46 &self.handler2
47 }
48
49 pub fn handler2_mut(&mut self) -> &mut H2 {
51 &mut self.handler2
52 }
53}
54
55#[derive(Error)]
57#[perfect_derive(Debug)]
58pub enum CombinedError<H1, H2>
59where
60 H1: HandleControlFlow,
61 H2: HandleControlFlow,
62{
63 #[error(transparent)]
65 H1Error(H1::Error),
66 #[error(transparent)]
68 H2Error(H2::Error),
69}
70
71impl<H1, H2> HandleControlFlow for CombinedControlFlowHandler<H1, H2>
72where
73 H1: HandleControlFlow,
74 H2: HandleControlFlow,
75{
76 type Error = CombinedError<H1, H2>;
77
78 #[cfg(feature = "cache")]
79 type CachedKey = (Option<H1::CachedKey>, Option<H2::CachedKey>);
80
81 fn at_decode_begin(&mut self) -> Result<(), Self::Error> {
82 self.handler1
83 .at_decode_begin()
84 .map_err(CombinedError::H1Error)?;
85 self.handler2
86 .at_decode_begin()
87 .map_err(CombinedError::H2Error)?;
88
89 Ok(())
90 }
91
92 fn on_new_block(
93 &mut self,
94 block_addr: u64,
95 transition_kind: super::ControlFlowTransitionKind,
96 cache: bool,
97 ) -> Result<(), Self::Error> {
98 self.handler1
99 .on_new_block(block_addr, transition_kind, cache)
100 .map_err(CombinedError::H1Error)?;
101 self.handler2
102 .on_new_block(block_addr, transition_kind, cache)
103 .map_err(CombinedError::H2Error)?;
104
105 Ok(())
106 }
107
108 #[cfg(feature = "cache")]
109 fn cache_prev_cached_key(
110 &mut self,
111 (cached_key1, cached_key2): Self::CachedKey,
112 ) -> Result<(), Self::Error> {
113 if let Some(cached_key) = cached_key1 {
114 self.handler1
115 .cache_prev_cached_key(cached_key)
116 .map_err(CombinedError::H1Error)?;
117 }
118 if let Some(cached_key) = cached_key2 {
119 self.handler2
120 .cache_prev_cached_key(cached_key)
121 .map_err(CombinedError::H2Error)?;
122 }
123
124 Ok(())
125 }
126
127 #[cfg(feature = "cache")]
128 fn take_cache(&mut self) -> Result<Option<Self::CachedKey>, Self::Error> {
129 let cached_key1 = self.handler1.take_cache().map_err(CombinedError::H1Error)?;
130 let cached_key2 = self.handler2.take_cache().map_err(CombinedError::H2Error)?;
131
132 Ok(Some((cached_key1, cached_key2)))
133 }
134
135 #[cfg(feature = "cache")]
136 fn clear_current_cache(&mut self) -> Result<(), Self::Error> {
137 self.handler1
138 .clear_current_cache()
139 .map_err(CombinedError::H1Error)?;
140 self.handler2
141 .clear_current_cache()
142 .map_err(CombinedError::H2Error)?;
143
144 Ok(())
145 }
146
147 #[cfg(feature = "cache")]
148 fn on_reused_cache(
149 &mut self,
150 (cached_key1, cached_key2): &Self::CachedKey,
151 new_bb: u64,
152 ) -> Result<(), Self::Error> {
153 if let Some(cached_key) = cached_key1 {
154 self.handler1
155 .on_reused_cache(cached_key, new_bb)
156 .map_err(CombinedError::H1Error)?;
157 }
158 if let Some(cached_key) = cached_key2 {
159 self.handler2
160 .on_reused_cache(cached_key, new_bb)
161 .map_err(CombinedError::H2Error)?;
162 }
163
164 Ok(())
165 }
166}