use crate::Resolver;
use commonware_cryptography::PublicKey;
use commonware_utils::{
channel::{fallible::AsyncFallibleExt, mpsc},
vec::NonEmptyVec,
Span,
};
type Predicate<K> = Box<dyn Fn(&K) -> bool + Send>;
pub struct FetchRequest<K, P> {
pub key: K,
pub targets: Option<NonEmptyVec<P>>,
}
pub enum Message<K, P> {
Fetch(Vec<FetchRequest<K, P>>),
Cancel { key: K },
Clear,
Retain { predicate: Predicate<K> },
}
#[derive(Clone)]
pub struct Mailbox<K, P> {
sender: mpsc::Sender<Message<K, P>>,
}
impl<K, P> Mailbox<K, P> {
pub(super) const fn new(sender: mpsc::Sender<Message<K, P>>) -> Self {
Self { sender }
}
}
impl<K: Span, P: PublicKey> Resolver for Mailbox<K, P> {
type Key = K;
type PublicKey = P;
async fn fetch(&mut self, key: Self::Key) {
self.sender
.send_lossy(Message::Fetch(vec![FetchRequest { key, targets: None }]))
.await;
}
async fn fetch_all(&mut self, keys: Vec<Self::Key>) {
self.sender
.send_lossy(Message::Fetch(
keys.into_iter()
.map(|key| FetchRequest { key, targets: None })
.collect(),
))
.await;
}
async fn fetch_targeted(&mut self, key: Self::Key, targets: NonEmptyVec<Self::PublicKey>) {
self.sender
.send_lossy(Message::Fetch(vec![FetchRequest {
key,
targets: Some(targets),
}]))
.await;
}
async fn fetch_all_targeted(
&mut self,
requests: Vec<(Self::Key, NonEmptyVec<Self::PublicKey>)>,
) {
self.sender
.send_lossy(Message::Fetch(
requests
.into_iter()
.map(|(key, targets)| FetchRequest {
key,
targets: Some(targets),
})
.collect(),
))
.await;
}
async fn cancel(&mut self, key: Self::Key) {
self.sender.send_lossy(Message::Cancel { key }).await;
}
async fn retain(&mut self, predicate: impl Fn(&Self::Key) -> bool + Send + 'static) {
self.sender
.send_lossy(Message::Retain {
predicate: Box::new(predicate),
})
.await;
}
async fn clear(&mut self) {
self.sender.send_lossy(Message::Clear).await;
}
}