You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.1 KiB
142 lines
3.1 KiB
//! 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.
|
|
type SESet<T> = smolset::SmolSet<[T; 1]>;
|
|
} else {
|
|
type SESet<T> = std::collections::HashSet<T>;
|
|
}
|
|
}
|
|
|
|
/// An event outputted from a state service's broadcast stream
|
|
#[derive(Debug, Clone)]
|
|
pub struct ServiceEvent
|
|
{
|
|
bc_id: BroadcastID,
|
|
|
|
kind: ServiceEventKind,
|
|
directed: Option<SESet<ServiceSubID>>,
|
|
obj: Option<ServiceEventObject>,
|
|
}
|
|
|
|
impl ServiceEvent
|
|
{
|
|
/// Create a new event to be broadcast
|
|
fn new<T>(kind: ServiceEventKind, directed: Option<impl IntoIterator<Item=ServiceSubID>>, obj: Option<T>) -> 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<Item = &'_ ServiceSubID> + '_
|
|
{
|
|
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<ServiceEventObject, Self>
|
|
{
|
|
match self.obj
|
|
{
|
|
Some(obj) => Ok(obj),
|
|
None => Err(self),
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl From<ServiceEvent> for Option<ServiceEventObject>
|
|
{
|
|
#[inline] fn from(from: ServiceEvent) -> Self
|
|
{
|
|
from.obj
|
|
}
|
|
}
|
|
|
|
impl TryFrom<ServiceEvent> for ServiceEventObject
|
|
{
|
|
type Error = NoObjectError;
|
|
|
|
#[inline] fn try_from(from: ServiceEvent) -> Result<Self, Self::Error>
|
|
{
|
|
match from.obj
|
|
{
|
|
Some(obj) => Ok(obj),
|
|
None => Err(NoObjectError),
|
|
}
|
|
}
|
|
}
|