#[cfg(feature = "magical_dyn")]
use std::any::Any;
#[cfg(feature = "magical_dyn")]
use std::boxed::Box;
#[cfg(feature = "magical_dyn")]
use std::vec::Vec;
#[cfg(feature = "magical_dyn")]
type MatcherBox = Box<dyn Fn(&[u8]) -> bool + Send + Sync>;
#[cfg(feature = "magical_dyn")]
pub struct DynMagicCustom {
matcher: MatcherBox,
kind: Box<dyn Any + Send + Sync>,
max_bytes_read: usize,
}
#[cfg(feature = "magical_dyn")]
impl DynMagicCustom {
#[must_use]
pub fn new<F, K>(matcher: F, kind: K, max_bytes_read: usize) -> Self
where
F: Fn(&[u8]) -> bool + 'static + Send + Sync,
K: 'static + Send + Sync,
{
Self {
matcher: Box::new(matcher),
kind: Box::new(kind),
max_bytes_read,
}
}
#[must_use]
pub fn matches(&self, bytes: &[u8]) -> bool {
(self.matcher)(bytes)
}
#[must_use]
pub fn kind(&self) -> &dyn Any {
self.kind.as_ref()
}
#[must_use]
pub fn kind_downcast_ref<T: 'static>(&self) -> Option<&T> {
self.kind.as_ref().downcast_ref::<T>()
}
#[must_use]
pub const fn max_bytes_read(&self) -> usize {
self.max_bytes_read
}
}
#[cfg(feature = "magical_dyn")]
#[must_use]
pub fn match_dyn_types<'a>(bytes: &[u8], rules: &'a [DynMagicCustom]) -> Option<&'a dyn Any> {
rules
.iter()
.find(|rule| rule.matches(bytes))
.map(DynMagicCustom::kind)
}
#[cfg(feature = "magical_dyn")]
#[must_use]
pub fn match_dyn_types_as<'a, T: 'static>(
bytes: &[u8],
rules: &'a [DynMagicCustom],
) -> Option<&'a T> {
match_dyn_types(bytes, rules)?.downcast_ref::<T>()
}
#[cfg(feature = "magical_dyn")]
#[must_use]
pub fn match_dyn_types_all<'a>(bytes: &[u8], rules: &'a [DynMagicCustom]) -> Vec<&'a dyn Any> {
rules
.iter()
.filter(|rule| rule.matches(bytes))
.map(DynMagicCustom::kind)
.collect()
}