use crate::entities::ListStyle;
use crate::types::EntityId;
#[derive(Default)]
pub struct ListGrouper {
active: Vec<Option<(EntityId, ListStyle)>>,
}
impl ListGrouper {
pub fn new() -> Self {
Self::default()
}
pub fn try_reuse(&mut self, style: &ListStyle, indent: u32) -> Option<EntityId> {
let idx = indent as usize;
self.active.truncate(idx + 1);
if let Some(Some((id, existing_style))) = self.active.get(idx)
&& existing_style == style
{
return Some(*id);
}
None
}
pub fn register(&mut self, id: EntityId, style: ListStyle, indent: u32) {
let idx = indent as usize;
while self.active.len() <= idx {
self.active.push(None);
}
self.active[idx] = Some((id, style));
}
pub fn reset(&mut self) {
self.active.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_item_returns_none() {
let mut g = ListGrouper::new();
assert!(g.try_reuse(&ListStyle::Decimal, 0).is_none());
}
#[test]
fn consecutive_same_style_reuses() {
let mut g = ListGrouper::new();
g.register(42, ListStyle::Decimal, 0);
assert_eq!(g.try_reuse(&ListStyle::Decimal, 0), Some(42));
}
#[test]
fn different_style_creates_new() {
let mut g = ListGrouper::new();
g.register(42, ListStyle::Decimal, 0);
assert!(g.try_reuse(&ListStyle::Disc, 0).is_none());
}
#[test]
fn different_indent_creates_new() {
let mut g = ListGrouper::new();
g.register(42, ListStyle::Decimal, 0);
assert!(g.try_reuse(&ListStyle::Decimal, 1).is_none());
}
#[test]
fn reset_clears_all() {
let mut g = ListGrouper::new();
g.register(42, ListStyle::Decimal, 0);
g.reset();
assert!(g.try_reuse(&ListStyle::Decimal, 0).is_none());
}
#[test]
fn nested_indent_resumes_outer() {
let mut g = ListGrouper::new();
g.register(10, ListStyle::Decimal, 0);
g.register(20, ListStyle::LowerAlpha, 1);
assert_eq!(g.try_reuse(&ListStyle::Decimal, 0), Some(10));
}
#[test]
fn nested_indent_different_style_creates_new() {
let mut g = ListGrouper::new();
g.register(10, ListStyle::Decimal, 0);
g.register(20, ListStyle::LowerAlpha, 1);
assert!(g.try_reuse(&ListStyle::Disc, 0).is_none());
}
}