use crate::text_expand::{ExpandResult, ExpandTask, ExpandUnit};
use std::collections::VecDeque;
pub struct EnPercentExpandTask;
impl ExpandTask for EnPercentExpandTask {
fn expand(&self, queue: &VecDeque<ExpandUnit>) -> Option<ExpandResult> {
if queue.len() < 2 {
if let Some(ExpandUnit::Number(_)) = queue.front() {
return Some(ExpandResult::Maybe);
}
return None;
}
match (queue.front(), queue.get(1)) {
(Some(ExpandUnit::Number(n)), Some(ExpandUnit::Mark('%'))) => {
Some(ExpandResult::Replace(
2,
vec![
ExpandUnit::Number(n.clone()),
ExpandUnit::Word("percent".into()),
],
))
}
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_en_percent_expansion() {
let task = EnPercentExpandTask;
let mut queue = VecDeque::new();
queue.push_back(ExpandUnit::Number("50".into()));
queue.push_back(ExpandUnit::Mark('%'));
let res = task.expand(&queue).unwrap();
if let ExpandResult::Replace(n, units) = res {
assert_eq!(n, 2);
assert_eq!(units[0], ExpandUnit::Number("50".into()));
assert_eq!(units[1], ExpandUnit::Word("percent".into()));
} else {
panic!("Expected Replace result");
}
}
#[test]
fn test_en_percent_zero() {
let task = EnPercentExpandTask;
let mut queue = VecDeque::new();
queue.push_back(ExpandUnit::Number("0".into()));
queue.push_back(ExpandUnit::Mark('%'));
let res = task.expand(&queue).unwrap();
if let ExpandResult::Replace(n, units) = res {
assert_eq!(n, 2);
assert_eq!(units[0], ExpandUnit::Number("0".into()));
assert_eq!(units[1], ExpandUnit::Word("percent".into()));
} else {
panic!("Expected Replace result for 0%");
}
}
#[test]
fn test_en_percent_maybe_single_number() {
let task = EnPercentExpandTask;
let mut queue = VecDeque::new();
queue.push_back(ExpandUnit::Number("50".into()));
let res = task.expand(&queue);
assert!(
matches!(res, Some(ExpandResult::Maybe)),
"Single number should return Maybe"
);
}
#[test]
fn test_en_percent_non_percent_mark_returns_none() {
let task = EnPercentExpandTask;
let mut queue = VecDeque::new();
queue.push_back(ExpandUnit::Number("50".into()));
queue.push_back(ExpandUnit::Mark('.'));
let res = task.expand(&queue);
assert!(
res.is_none(),
"Number followed by '.' should not expand as percent"
);
}
#[test]
fn test_en_percent_non_number_returns_none() {
let task = EnPercentExpandTask;
let mut queue = VecDeque::new();
queue.push_back(ExpandUnit::Word("hello".into()));
let res = task.expand(&queue);
assert!(res.is_none(), "Non-number input should return None");
}
}