use super::*;
use crate::merger::MergeCtxType;
use crate::ResolvedFold;
use num_traits::ops::checked::CheckedAdd;
#[derive(Debug, Default, Clone)]
pub(super) struct CtxStateHandler {
state_pair: CtxStatesPair,
}
impl CtxStateHandler {
pub(super) fn prepare(
prev_fold: &ResolvedFold,
current_fold: &ResolvedFold,
data_keeper: &DataKeeper,
) -> FSMResult<Self> {
let prev_state = compute_new_state(prev_fold, data_keeper, MergeCtxType::Previous)?;
let current_state = compute_new_state(current_fold, data_keeper, MergeCtxType::Current)?;
let state_pair = CtxStatesPair::new(prev_state, current_state);
let updater = Self { state_pair };
Ok(updater)
}
pub(super) fn set_final_states(self, data_keeper: &mut DataKeeper) {
update_ctx_states(self.state_pair, data_keeper)
}
}
fn compute_new_state(fold: &ResolvedFold, data_keeper: &DataKeeper, ctx_type: MergeCtxType) -> FSMResult<CtxState> {
let ctx = match ctx_type {
MergeCtxType::Previous => &data_keeper.prev_ctx,
MergeCtxType::Current => &data_keeper.current_ctx,
};
let current_position = ctx.slider.position();
let pos = current_position
.checked_add(&fold.fold_states_count.into())
.ok_or_else(|| StateFSMError::FoldPosOverflow(fold.clone(), current_position, ctx_type))?;
let current_len = ctx.slider.subtrace_len();
let subtrace_len = current_len
.checked_sub(fold.fold_states_count)
.ok_or_else(|| StateFSMError::FoldLenUnderflow(fold.clone(), current_position, ctx_type))?;
let state = CtxState::new(pos, subtrace_len);
Ok(state)
}