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.
102 lines
2.5 KiB
102 lines
2.5 KiB
//! Commands for a service
|
|
use super::*;
|
|
use std::{any::Any, marker::{Send, Sync}};
|
|
use std::fmt;
|
|
use tokio::sync::{
|
|
oneshot,
|
|
};
|
|
|
|
id_type!(pub CommandID: "ID of a sent command");
|
|
|
|
/// A response from the service for a sent command
|
|
pub type Response = Box<dyn Any + Send + 'static>;
|
|
|
|
/// What kind of command to send to the service?
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
pub enum CommandKind
|
|
{
|
|
|
|
}
|
|
|
|
/// A command to send to a running service.
|
|
///
|
|
/// Created when sending a `CommandKind` to a service. This is your handle for receiving the response.
|
|
#[derive(Debug)]
|
|
pub struct Command
|
|
{
|
|
id: CommandID,
|
|
//kind: CommandKind, // `CommandKind` -(sent to)> <running service> -(handle returned from send func)> `Command`
|
|
|
|
resp: oneshot::Receiver<Option<Response>>,
|
|
}
|
|
|
|
|
|
impl fmt::Display for Command
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
{
|
|
write!(f, "CommandID<{}>", self.id.0.as_bytes().hex())
|
|
}
|
|
}
|
|
|
|
|
|
impl Command
|
|
{
|
|
/// The unique ID of this command
|
|
#[inline] pub fn id(&self) -> &CommandID
|
|
{
|
|
&self.id
|
|
}
|
|
|
|
/// Prevent any response from being sent to this `Command` handle from the service.
|
|
///
|
|
/// Indicates to the service we don't care about a response. This has the same effect as calling `ignore` but can be used in a builder-pattern way from a returned `Command` from a send.
|
|
/// Example: `let comm = service.send_command(comm_kind).ignored();`
|
|
#[inline(always)] pub fn ignored(mut self) -> Self
|
|
{
|
|
self.ignore();
|
|
self
|
|
}
|
|
|
|
/// Close the response channel, indicating to the service that we don't care about the response.
|
|
#[inline] pub fn ignore(&mut self)
|
|
{
|
|
self.resp.close();
|
|
}
|
|
|
|
/// Dispose of this `Command`, returning any `Response` that might've already been sent.
|
|
#[inline] pub fn close(mut self) -> Option<Response>
|
|
{
|
|
use oneshot::error::TryRecvError;
|
|
|
|
self.resp.close();
|
|
self.resp.try_recv().ok().flatten()
|
|
}
|
|
|
|
/// Poll for a response. If none has been sent yet, then return `self` so it can be polled again.
|
|
#[inline] pub fn try_into_response(mut self) -> Result<Option<Response>, Self>
|
|
{
|
|
use oneshot::error::TryRecvError;
|
|
|
|
match self.resp.try_recv() {
|
|
Ok(v) => Ok(v),
|
|
Err(TryRecvError::Closed) => Ok(None),
|
|
Err(TryRecvError::Empty) => Err(self),
|
|
}
|
|
}
|
|
|
|
/// Consume this instance into the response from the service.
|
|
#[inline] pub async fn into_repsonse(self) -> Option<Response>
|
|
{
|
|
self.resp.await.ok().flatten()
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Command
|
|
{
|
|
#[inline] fn eq(&self, other: &Self) -> bool
|
|
{
|
|
self.id == other.id
|
|
}
|
|
}
|