use std::marker::PhantomData;
use crate::analysis::cpa::residue::Residue;
use crate::analysis::cpa::state::AbstractState;
pub struct FinalReducer<S>
where
S: AbstractState,
{
all_states: Vec<S>,
non_final_states: Vec<S>,
_phantom: PhantomData<S>,
}
impl<S> FinalReducer<S>
where
S: AbstractState,
{
pub fn new_with_capacity(cap: usize) -> Self {
Self {
all_states: Vec::with_capacity(cap),
non_final_states: Vec::with_capacity(cap),
_phantom: Default::default(),
}
}
fn compute_final_states(self) -> Vec<S> {
let mut final_states = Vec::new();
for state in self.all_states {
if !self.non_final_states.iter().any(|s| s == &state) {
final_states.push(state);
}
}
final_states
}
}
impl<S> Default for FinalReducer<S>
where
S: AbstractState,
{
fn default() -> Self {
Self {
all_states: Vec::new(),
non_final_states: Vec::new(),
_phantom: Default::default(),
}
}
}
impl<S> Residue<S> for FinalReducer<S>
where
S: AbstractState,
{
type Output = Vec<S>;
fn new_state(
&mut self,
state: &S,
dest_state: &S,
_op: &Option<crate::analysis::pcode_store::PcodeOpRef<'_>>,
) {
if !self.non_final_states.iter().any(|s| s == state) {
self.non_final_states.push(state.clone());
}
if !self.all_states.iter().any(|s| s == dest_state) {
self.all_states.push(dest_state.clone());
}
}
fn merged_state(
&mut self,
curr_state: &S,
original_merged_state: &S,
merged_state: &S,
_op: &Option<crate::analysis::pcode_store::PcodeOpRef<'_>>,
) {
if !self.non_final_states.iter().any(|s| s == curr_state) {
self.non_final_states.push(curr_state.clone());
}
for state in &mut self.all_states {
if state == original_merged_state {
*state = merged_state.clone();
}
}
for state in &mut self.non_final_states {
if state == original_merged_state {
*state = merged_state.clone();
}
}
}
fn new() -> Self {
Self::default()
}
fn finalize(self) -> Self::Output {
self.compute_final_states()
}
}