use super::Effect;
pub struct EffectSink {
buf: Vec<Effect>,
}
impl EffectSink {
pub fn new() -> Self {
Self {
buf: Vec::with_capacity(8),
}
}
#[inline]
pub fn push(&mut self, e: Effect) {
self.buf.push(e);
}
#[inline]
pub fn clear(&mut self) {
self.buf.clear();
}
#[inline]
pub fn as_slice(&self) -> &[Effect] {
&self.buf
}
pub fn retain_mut_from(&mut self, start: usize, mut keep: impl FnMut(&mut Effect) -> bool) {
let mut index = 0;
self.buf.retain_mut(|effect| {
let retained = index < start || keep(effect);
index += 1;
retained
});
}
#[inline]
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
}
impl Default for EffectSink {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::effect::{DomainEventBytes, TimerId};
#[test]
fn retain_suffix_preserves_prefix_and_nonmatching_effects() {
let mut sink = EffectSink::new();
sink.push(Effect::Emit {
event: DomainEventBytes(bytes::Bytes::from_static(b"prefix")),
});
sink.push(Effect::Emit {
event: DomainEventBytes(bytes::Bytes::from_static(b"remove")),
});
sink.push(Effect::CancelTimer {
id: TimerId::from_raw(1),
});
sink.retain_mut_from(1, |effect| !matches!(effect, Effect::Emit { .. }));
assert_eq!(sink.as_slice().len(), 2);
assert!(matches!(&sink.as_slice()[0],Effect::Emit{event} if event.0.as_ref()==b"prefix"));
assert!(matches!(&sink.as_slice()[1], Effect::CancelTimer { .. }));
}
}