use crate::model::ModelEvent;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", content = "payload")]
pub enum InputPayload<E: ModelEvent> {
Event(E),
Command(CommandInput),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum CommandInput {
Start,
Stop,
Restart,
HotReload(Value),
Shutdown,
Kill,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct InputMeta {
pub id: Uuid,
pub source: Option<String>,
}
impl Default for InputMeta {
fn default() -> Self {
Self {
id: Uuid::new_v4(),
source: None,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Input<E: ModelEvent> {
#[serde(flatten)]
pub payload: InputPayload<E>,
pub meta: Option<InputMeta>,
}
impl<E: ModelEvent> Input<E> {
pub fn new(payload: InputPayload<E>) -> Self {
Self {
payload,
meta: None,
}
}
pub fn event(ev: E) -> Self {
Self::new(InputPayload::Event(ev))
}
pub fn command(cmd: CommandInput) -> Self {
Self::new(InputPayload::Command(cmd))
}
pub fn with_meta(mut self, meta: InputMeta) -> Self {
self.meta = Some(meta);
self
}
pub fn with_id(mut self, id: Uuid) -> Self {
Self::ensure_meta(&mut self.meta);
self.meta.as_mut().unwrap().id = id;
self
}
pub fn with_source(mut self, source: impl Into<String>) -> Self {
Self::ensure_meta(&mut self.meta);
self.meta.as_mut().unwrap().source = Some(source.into());
self
}
pub fn id(&self) -> Option<Uuid> {
self.meta.as_ref().map(|m| m.id)
}
pub fn source(&self) -> Option<&str> {
self.meta.as_ref().and_then(|m| m.source.as_deref())
}
pub fn is_event(&self) -> bool {
matches!(self.payload, InputPayload::Event(_))
}
pub fn is_command(&self) -> bool {
matches!(self.payload, InputPayload::Command(_))
}
pub fn map_event<T: ModelEvent>(self, f: impl FnOnce(E) -> T) -> Input<T> {
let payload = match self.payload {
InputPayload::Event(ev) => InputPayload::Event(f(ev)),
InputPayload::Command(c) => InputPayload::Command(c),
};
Input {
payload,
meta: self.meta,
}
}
pub fn meta_mut(&mut self) -> &mut InputMeta {
Self::ensure_meta(&mut self.meta);
self.meta.as_mut().unwrap()
}
fn ensure_meta(meta: &mut Option<InputMeta>) {
if meta.is_none() {
*meta = Some(InputMeta::default());
}
}
}
impl<E: ModelEvent> From<E> for Input<E> {
fn from(ev: E) -> Self {
Input::event(ev)
}
}
impl<E: ModelEvent> From<CommandInput> for Input<E> {
fn from(cmd: CommandInput) -> Self {
Input::command(cmd)
}
}