#[cfg(feature = "magical_async_dyn")]
use {core::pin::Pin, std::any::Any, std::boxed::Box, std::future::Future, std::sync::Arc};
#[cfg(feature = "magical_async_dyn")]
type AsyncMatcher =
Box<dyn Fn(&[u8]) -> Pin<Box<dyn Future<Output = bool> + Send + 'static>> + Send + Sync>;
#[cfg(feature = "magical_async_dyn")]
pub struct AsyncDynMagic {
matcher: AsyncMatcher,
kind: Arc<dyn Any + Send + Sync>,
max_bytes_read: usize,
}
#[cfg(feature = "magical_async_dyn")]
impl AsyncDynMagic {
#[must_use]
pub fn new<F, Fut, K>(matcher: F, kind: K, max_bytes_read: usize) -> Self
where
F: Fn(&[u8]) -> Fut + Send + Sync + 'static,
Fut: Future<Output = bool> + Send + 'static,
K: 'static + Send + Sync,
{
Self {
matcher: Box::new(move |bytes| Box::pin(matcher(bytes))),
kind: Arc::new(kind),
max_bytes_read,
}
}
#[must_use]
pub async fn matches(&self, bytes: &[u8]) -> bool {
(self.matcher)(bytes).await
}
#[must_use]
pub fn kind_arc(&self) -> Arc<dyn Any + Send + Sync> {
self.kind.clone()
}
#[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_async_dyn")]
#[must_use]
pub async fn match_dyn_types<'a>(bytes: &[u8], rules: &'a [AsyncDynMagic]) -> Option<&'a dyn Any> {
for rule in rules {
if rule.matches(bytes).await {
return Some(rule.kind());
}
}
None
}
#[cfg(feature = "magical_async_dyn")]
#[must_use]
pub async fn match_dyn_types_as<'a, T: 'static>(
bytes: &[u8],
rules: &'a [AsyncDynMagic],
) -> Option<&'a T> {
match_dyn_types(bytes, rules).await?.downcast_ref::<T>()
}
#[cfg(feature = "magical_async_dyn")]
#[must_use]
pub async fn match_dyn_types_all(
bytes: &[u8],
rules: &[AsyncDynMagic],
) -> Vec<Arc<dyn Any + Send + Sync>> {
let mut results = Vec::new();
for rule in rules {
if rule.matches(bytes).await {
results.push(rule.kind_arc());
}
}
results
}