use super::{ExecuteError, Result};
use super::tag_answer::{AnswerState, AnswerStatus};
use super::tag_inline::{InlineState, InlineStatus};
use super::tags::{Container, StaticPolicy, StaticPolicyMonoInput, StaticPolicyMonoResult};
use crate::ast2::CommandKind;
pub struct RepeatPolicy;
impl StaticPolicy for RepeatPolicy {
fn mono(inputs: StaticPolicyMonoInput) -> Result<StaticPolicyMonoResult> {
let (mut result, residual) = StaticPolicyMonoResult::from_inputs(inputs);
let tag = match residual.container {
Container::Tag(tag) => tag,
_ => {
panic!("!?!?!? cannot be anchor in static tag !?!?!?"); }
};
match result.collector.anchor_stack().last() {
Some(anchor) => {
let is_anchor_repeatable = match anchor.command {
CommandKind::Answer => {
let mut answer_state = residual
.worker
.load_state::<AnswerState>(anchor.command, &anchor.uuid)?;
answer_state.status = AnswerStatus::Repeat;
residual.worker.save_state::<AnswerState>(
anchor.command,
&anchor.uuid,
&answer_state,
None,
)?;
true
}
CommandKind::Inline => {
let mut inline_state = residual
.worker
.load_state::<InlineState>(anchor.command, &anchor.uuid)?;
inline_state.status = InlineStatus::Repeat;
residual.worker.save_state::<InlineState>(
anchor.command,
&anchor.uuid,
&inline_state,
None,
)?;
true
}
_ => false,
};
if !is_anchor_repeatable {
return Err(ExecuteError::RepeatNotAllowed { range: tag.range });
}
if !residual.readonly {
let mutated_anchor = anchor.update(residual.parameters, residual.arguments);
let mutated_anchor_patch = residual.worker.mutate_anchor(&mutated_anchor)?;
let elide_repeat_patch = (tag.range, String::new());
result.new_patches = vec![mutated_anchor_patch, elide_repeat_patch];
}
result.do_next_pass = true;
}
None => {
return Err(ExecuteError::RepeatNotInAnchor { range: tag.range });
}
};
Ok(result)
}
}