use std::sync::Arc;
use super::{Interaction, InteractionPattern, Kind, Label, Length};
use crate::pattern::Hierarchy;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct PatternPlayer {
pattern: Arc<InteractionPattern>,
position: usize,
finalized: bool,
}
impl PatternPlayer {
#[must_use]
pub const fn new(pattern: Arc<InteractionPattern>) -> Self {
Self {
pattern,
position: 0,
finalized: false,
}
}
pub fn finalize(mut self) {
assert!(self.position <= self.pattern.interactions().len());
assert!(!self.finalized, "Transcript is already finalized.");
assert!(
self.position >= self.pattern.interactions().len(),
"Transcript not finished, expecting {}",
self.pattern.interactions()[self.position]
);
self.finalized = true;
}
pub fn interact(&mut self, interaction: Interaction) {
assert!(!self.finalized, "Transcript is already finalized.");
let Some(expected) = self.pattern.interactions().get(self.position) else {
self.finalized = true;
panic!("Received interaction, but no more expected interactions: {interaction}");
};
if expected != &interaction {
self.finalized = true;
panic!("Received interaction {interaction}, but expected {expected}");
}
self.position += 1;
}
}
impl Drop for PatternPlayer {
fn drop(&mut self) {
assert!(self.finalized, "Dropped unfinalized transcript.");
}
}
impl super::Pattern for PatternPlayer {
fn abort(&mut self) {
assert!(!self.finalized, "Transcript is already finalized.");
self.finalized = true;
}
fn begin<T: ?Sized>(&mut self, label: Label, kind: Kind, length: Length) {
self.interact(Interaction::new::<T>(Hierarchy::Begin, kind, label, length));
}
fn end<T: ?Sized>(&mut self, label: Label, kind: Kind, length: Length) {
self.interact(Interaction::new::<T>(Hierarchy::End, kind, label, length));
}
}