use core::fmt;
use crate::Listener;
#[derive(Clone)]
pub struct Filter<F, T, const BATCH: usize> {
pub(super) function: F,
pub(super) target: T,
}
impl<F, T> Filter<F, T, 1> {
pub fn with_stack_buffer<const BATCH: usize>(self) -> Filter<F, T, BATCH> {
Filter {
function: self.function,
target: self.target,
}
}
}
impl<F, T: fmt::Debug, const BATCH: usize> fmt::Debug for Filter<F, T, BATCH> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Filter")
.field(
"function",
&crate::util::Unquote::type_name_of(&self.function),
)
.field("target", &self.target)
.finish()
}
}
impl<F, T: fmt::Pointer, const BATCH: usize> fmt::Pointer for Filter<F, T, BATCH> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
T::fmt(&self.target, f)
}
}
impl<MI, MO, F, T, const BATCH: usize> Listener<MI> for Filter<F, T, BATCH>
where
F: Fn(&MI) -> Option<MO> + Send + Sync,
T: Listener<MO>,
{
fn receive(&self, messages: &[MI]) -> bool {
if const { size_of::<MO>() == 0 } {
let mut filtered_messages = alloc::vec::Vec::<MO>::new();
for message in messages {
if let Some(filtered_message) = (self.function)(message) {
filtered_messages.push(filtered_message);
}
}
self.target.receive(filtered_messages.as_slice())
} else {
let mut buffer: arrayvec::ArrayVec<MO, BATCH> = arrayvec::ArrayVec::new();
for message in messages {
if let Some(filtered_message) = (self.function)(message) {
if buffer.is_full() {
let alive = self.target.receive(&buffer);
if !alive {
return false;
}
buffer.clear();
}
buffer.push(filtered_message);
}
}
self.target.receive(&buffer)
}
}
}
impl<MI, MO, F, T: Listener<MO>, const BATCH: usize> crate::FromListener<Filter<F, T, BATCH>, MI>
for Filter<F, T, BATCH>
where
F: Fn(&MI) -> Option<MO> + Send + Sync,
T: Listener<MO>,
{
fn from_listener(listener: Filter<F, T, BATCH>) -> Self {
listener
}
}