use arrayvec::{ArrayVec, IntoIter as ArrayVecIntoIter};
use crate::event::DomainEvent;
use core::iter::{Chain, Once, once};
#[macro_export]
macro_rules! events {
[$head:expr] => {
$crate::Events::new($head)
};
[$head:expr, $($tail:expr),+ $(,)?] => {
{
let mut events = $crate::Events::new($head);
$(
events.add($tail);
)*
events
}
};
}
#[derive(Debug)]
pub struct Events<E: DomainEvent, const N: usize = 0> {
first: E,
rest: ArrayVec<E, N>,
}
impl<E: DomainEvent, const N: usize> Events<E, N> {
#[must_use]
pub fn new(event: E) -> Self {
Self {
first: event,
rest: ArrayVec::new(),
}
}
#[allow(
clippy::expect_used,
reason = "capacity overflow is a programmer bug, enforced by Handle<C, N>"
)]
pub fn add(&mut self, event: E) {
self.rest.try_push(event).expect(
"Events capacity exceeded: the Handle trait's N parameter must match the maximum number of additional events",
);
}
pub fn iter(&self) -> Chain<Once<&E>, core::slice::Iter<'_, E>> {
once(&self.first).chain(self.rest.iter())
}
#[must_use]
pub const fn len(&self) -> usize {
self.rest.len() + 1
}
#[must_use]
pub const fn is_empty(&self) -> bool {
false
}
}
impl<E: DomainEvent + Clone, const N: usize> Clone for Events<E, N> {
fn clone(&self) -> Self {
Self {
first: self.first.clone(),
rest: self.rest.clone(),
}
}
}
impl<E: DomainEvent + PartialEq, const N: usize> PartialEq for Events<E, N> {
fn eq(&self, other: &Self) -> bool {
self.first == other.first && self.rest == other.rest
}
}
impl<E: DomainEvent + Eq, const N: usize> Eq for Events<E, N> {}
impl<E: DomainEvent, const N: usize> From<E> for Events<E, N> {
fn from(event: E) -> Self {
Self::new(event)
}
}
#[derive(Debug)]
pub struct EventsIntoIter<E: DomainEvent, const N: usize> {
inner: Chain<Once<E>, ArrayVecIntoIter<E, N>>,
}
impl<E: DomainEvent, const N: usize> Iterator for EventsIntoIter<E, N> {
type Item = E;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<E: DomainEvent, const N: usize> DoubleEndedIterator for EventsIntoIter<E, N> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<E: DomainEvent, const N: usize> core::iter::FusedIterator for EventsIntoIter<E, N> {}
impl<E: DomainEvent, const N: usize> IntoIterator for Events<E, N> {
type Item = E;
type IntoIter = EventsIntoIter<E, N>;
fn into_iter(self) -> Self::IntoIter {
EventsIntoIter {
inner: once(self.first).chain(self.rest),
}
}
}
impl<'a, E: DomainEvent, const N: usize> IntoIterator for &'a Events<E, N> {
type Item = &'a E;
type IntoIter = Chain<Once<&'a E>, core::slice::Iter<'a, E>>;
fn into_iter(self) -> Self::IntoIter {
once(&self.first).chain(self.rest.iter())
}
}