use {
crate::{DatalineWriter, DatastarEvent, consts},
core::{fmt, time::Duration},
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PatchSignals {
pub id: Option<String>,
pub retry: Duration,
pub signals: String,
pub only_if_missing: bool,
}
impl PatchSignals {
pub fn new(signals: impl Into<String>) -> Self {
Self {
id: None,
retry: Duration::from_millis(consts::DEFAULT_SSE_RETRY_DURATION),
signals: signals.into(),
only_if_missing: consts::DEFAULT_PATCH_SIGNALS_ONLY_IF_MISSING,
}
}
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn retry(mut self, retry: Duration) -> Self {
self.retry = retry;
self
}
pub fn only_if_missing(mut self, only_if_missing: bool) -> Self {
self.only_if_missing = only_if_missing;
self
}
#[inline]
pub fn into_datastar_event(mut self) -> DatastarEvent {
let id = self.id.take();
self.convert_to_datastar_event_inner(id)
}
#[inline]
pub fn as_datastar_event(&self) -> DatastarEvent {
self.convert_to_datastar_event_inner(self.id.clone())
}
fn convert_to_datastar_event_inner(&self, id: Option<String>) -> DatastarEvent {
let mut data: Vec<String> = Vec::new();
self.write_datalines(&mut data)
.expect("writing datalines to a Vec cannot fail");
DatastarEvent {
event: consts::EventType::PatchSignals,
id,
retry: self.retry,
data,
}
}
pub(crate) fn write_datalines(&self, writer: &mut impl DatalineWriter) -> fmt::Result {
if self.only_if_missing != consts::DEFAULT_PATCH_SIGNALS_ONLY_IF_MISSING {
writer.write_dataline(format_args!(
"{} {}",
consts::ONLY_IF_MISSING_DATALINE_LITERAL,
self.only_if_missing
))?;
}
for line in self.signals.lines() {
writer.write_dataline(format_args!("{} {line}", consts::SIGNALS_DATALINE_LITERAL))?;
}
Ok(())
}
}
impl From<&PatchSignals> for DatastarEvent {
#[inline]
fn from(val: &PatchSignals) -> Self {
val.as_datastar_event()
}
}
impl From<PatchSignals> for DatastarEvent {
#[inline]
fn from(val: PatchSignals) -> Self {
val.into_datastar_event()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn patch() -> PatchSignals {
PatchSignals::new("{foo: 1,\nbar: 2}")
.id("signals-1")
.retry(Duration::from_millis(2_000))
.only_if_missing(true)
}
fn assert_event(event: DatastarEvent) {
assert_eq!(event.event, consts::EventType::PatchSignals);
assert_eq!(event.id.as_deref(), Some("signals-1"));
assert_eq!(event.retry, Duration::from_millis(2_000));
assert_eq!(
event.data,
["onlyIfMissing true", "signals {foo: 1,", "signals bar: 2}"]
);
}
#[test]
fn serializes_options_and_conversions() {
let patch = patch();
assert_event(patch.as_datastar_event());
assert_event(DatastarEvent::from(&patch));
assert_event(patch.clone().into_datastar_event());
assert_event(DatastarEvent::from(patch));
}
#[test]
fn omits_default_options() {
let event = PatchSignals::new("{foo: 1}").into_datastar_event();
assert_eq!(event.data, ["signals {foo: 1}"]);
}
}