use std::{ any::Any, collections::HashSet, mem, sync::{Arc, Mutex, MutexGuard}, }; use web_push::{PartialVapidSignatureBuilder, SubscriptionInfo}; use crate::{error::failed::Failed, push::Publish}; #[derive(Clone)] pub struct Client(Arc>); #[derive(Default)] struct ClientInner { sent: Vec, } impl Client { pub fn new() -> Self { Self(Arc::default()) } fn inner(&self) -> MutexGuard<'_, ClientInner> { self.0.lock().unwrap() } // Clears the list of sent messages (for all clones of this Client) when called, because we // can't clone `Publications`s, so we either need to move them or try to reconstruct them. pub fn sent(&self) -> Vec { let sent = &mut self.inner().sent; mem::take(sent) } } #[async_trait::async_trait] impl Publish for Client { async fn publish( &self, message: M, _: &PartialVapidSignatureBuilder, subscriptions: impl IntoIterator + Send, ) -> Result<(), Failed> where M: Send + 'static, { let mut inner = self.inner(); let message: Box = Box::new(message); let recipients = subscriptions.into_iter().cloned().collect(); let publication = Publication { message, recipients, }; inner.sent.push(publication); Ok(()) } } #[derive(Debug)] pub struct Publication { pub message: Box, pub recipients: HashSet, } impl Publication { pub fn message_eq(&self, candidate: &M) -> bool where M: PartialEq + 'static, { match self.message.downcast_ref::() { None => false, Some(message) => message == candidate, } } }