use std::collections::HashMap;
use crate::{Cursor, ReadReply, StepRow};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Applied {
Added,
Replaced,
}
#[derive(Clone, Debug, Default)]
pub struct LatestRows {
rows: Vec<StepRow>,
index: HashMap<(String, String), usize>,
resume_after: Option<Cursor>,
}
impl LatestRows {
pub fn new() -> Self {
Self::default()
}
pub fn apply(&mut self, row: StepRow) -> Applied {
let key = (row.harness.clone(), row.step_ref.clone());
match self.index.get(&key) {
Some(&slot) => {
self.rows[slot] = row;
Applied::Replaced
}
None => {
self.index.insert(key, self.rows.len());
self.rows.push(row);
Applied::Added
}
}
}
pub fn apply_reply(&mut self, reply: ReadReply) {
self.resume_after = Some(reply.resume_after().clone());
for row in reply.rows {
self.apply(row);
}
}
pub fn resume_after(&self) -> Option<&Cursor> {
self.resume_after.as_ref()
}
pub fn get(&self, harness: &str, step_ref: &str) -> Option<&StepRow> {
self.index
.get(&(harness.to_owned(), step_ref.to_owned()))
.map(|&slot| &self.rows[slot])
}
pub fn iter(&self) -> impl Iterator<Item = &StepRow> {
self.rows.iter()
}
pub fn len(&self) -> usize {
self.rows.len()
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
pub fn clear(&mut self) {
*self = Self::default();
}
}