#[derive(Debug, Clone)]
pub enum StageOutcome {
Continue,
Complete,
NeedMoreData {
additional_beam: usize,
go_deeper: bool,
},
Backtrack {
target_stage: String,
reason: String,
},
Skip {
reason: String,
},
}
impl StageOutcome {
pub fn cont() -> Self {
Self::Continue
}
pub fn complete() -> Self {
Self::Complete
}
pub fn need_more(additional_beam: usize, go_deeper: bool) -> Self {
Self::NeedMoreData {
additional_beam,
go_deeper,
}
}
pub fn backtrack(target: impl Into<String>, reason: impl Into<String>) -> Self {
Self::Backtrack {
target_stage: target.into(),
reason: reason.into(),
}
}
pub fn skip(reason: impl Into<String>) -> Self {
Self::Skip {
reason: reason.into(),
}
}
pub fn is_complete(&self) -> bool {
matches!(self, Self::Complete | Self::Skip { .. })
}
pub fn needs_backtrack(&self) -> bool {
matches!(self, Self::Backtrack { .. } | Self::NeedMoreData { .. })
}
pub fn backtrack_target(&self) -> Option<&str> {
match self {
Self::Backtrack { target_stage, .. } => Some(target_stage),
Self::NeedMoreData { .. } => Some("search"),
_ => None,
}
}
}
impl Default for StageOutcome {
fn default() -> Self {
Self::Continue
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_outcome_constructors() {
assert!(matches!(StageOutcome::cont(), StageOutcome::Continue));
assert!(matches!(StageOutcome::complete(), StageOutcome::Complete));
}
#[test]
fn test_need_more() {
let outcome = StageOutcome::need_more(2, true);
assert!(outcome.needs_backtrack());
assert_eq!(outcome.backtrack_target(), Some("search"));
}
#[test]
fn test_backtrack() {
let outcome = StageOutcome::backtrack("plan", "strategy not working");
assert!(outcome.needs_backtrack());
assert_eq!(outcome.backtrack_target(), Some("plan"));
}
#[test]
fn test_is_complete() {
assert!(StageOutcome::complete().is_complete());
assert!(StageOutcome::skip("reason").is_complete());
assert!(!StageOutcome::cont().is_complete());
}
}