//! Controls the broadcasting of events sent from the state service task use super::*; /// The kind of event outputted from a state service's broadcast stream #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] pub enum ServiceEventKind { /// Does nothing. /// /// # Associated object /// `()`. Ping, /// Does nothing. /// /// # Associated object /// None. KeepAlive, } cfg_if!{ if #[cfg(debug_assertions)] { /// Type used for directed array. /// Currently testing `smolset` over eagerly allocating. pub(super) type SESet = smolset::SmolSet<[T; 1]>; } else { pub(super) type SESet = std::collections::HashSet; } } /// An event outputted from a state service's broadcast stream #[derive(Debug, Clone)] pub struct ServiceEvent { bc_id: BroadcastID, kind: ServiceEventKind, directed: Option>, obj: Option, } impl ServiceEvent { /// Create a new event to be broadcast fn new(kind: ServiceEventKind, directed: Option>, obj: Option) -> Self where T: Any + Send + Sync + 'static { Self { bc_id: BroadcastID::id_new(), kind, directed: directed.map(|x| x.into_iter().collect()).and_then(|n: SESet<_>| if n.len() < 1 { None } else { Some(n) }), obj: obj.map(|x| ServiceEventObject(Arc::new(x))), } } #[inline] pub fn id(&self) -> &BroadcastID { &self.bc_id } /// The kind of this event. #[inline] pub fn kind(&self) -> ServiceEventKind { self.kind } /// Check if this event is for you pub fn is_directed_for(&self, whom: &ServiceSubID) -> bool { if let Some(yes) = self.directed.as_ref() { yes.contains(whom) } else { false } } /// Check if this event is directed to anyone pub fn is_directed(&self) -> bool { self.directed.is_some() } /// Check who this event is directed to. /// /// If it is not directed, an empty slice will be returned. pub fn directed_to(&self) -> impl Iterator + '_ { match self.directed.as_ref() { Some(yes) => MaybeIter::many(yes.iter()), None => MaybeIter::none(), } } /// Get a reference to the object, if there is one. pub fn obj_ref(&self) -> Option<&ServiceEventObject> { self.obj.as_ref() } /// Get a mutable reference to the object, if there is one. pub fn obj_mut(&mut self) -> Option<&mut ServiceEventObject> { self.obj.as_mut() } /// Try to consume into the inner object. If there is no object, return self. pub fn try_into_object(self) -> Result { match self.obj { Some(obj) => Ok(obj), None => Err(self), } } } impl From for Option { #[inline] fn from(from: ServiceEvent) -> Self { from.obj } } impl TryFrom for ServiceEventObject { type Error = NoObjectError; #[inline] fn try_from(from: ServiceEvent) -> Result { match from.obj { Some(obj) => Ok(obj), None => Err(NoObjectError), } } }