use std::future::Future;
use crate::Action;
pub struct Cmd<Msg> {
pub action: Action<Msg>,
pub dirty: bool,
}
impl<Msg> Cmd<Msg> {
pub fn none() -> Self {
Cmd {
action: Action::None,
dirty: false,
}
}
pub fn dirty() -> Self {
Cmd {
action: Action::None,
dirty: true,
}
}
pub fn quit() -> Self {
Cmd {
action: Action::Quit,
dirty: false,
}
}
pub fn task<F>(future: F) -> Self
where
F: Future<Output = Msg> + Send + 'static,
{
Cmd {
action: Action::task(future),
dirty: true,
}
}
pub fn batch(actions: Vec<Action<Msg>>) -> Self {
Cmd {
action: Action::Batch(actions),
dirty: true,
}
}
pub fn dirty_with_action(action: Action<Msg>) -> Self {
Cmd {
action,
dirty: true,
}
}
pub fn with_action(action: Action<Msg>, dirty: bool) -> Self {
Cmd { action, dirty }
}
pub fn map<N, F>(self, f: F) -> Cmd<N>
where
Msg: Send + 'static,
N: Send + 'static,
F: FnOnce(Msg) -> N + Send + 'static + Clone,
{
Cmd {
action: self.action.map(f),
dirty: self.dirty,
}
}
}
impl<Msg> std::fmt::Debug for Cmd<Msg> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Cmd")
.field("action", &self.action)
.field("dirty", &self.dirty)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn none_is_clean() {
let cmd: Cmd<()> = Cmd::none();
assert!(!cmd.dirty);
assert!(matches!(cmd.action, Action::None));
}
#[test]
fn dirty_is_dirty() {
let cmd: Cmd<()> = Cmd::dirty();
assert!(cmd.dirty);
assert!(matches!(cmd.action, Action::None));
}
#[test]
fn quit_action() {
let cmd: Cmd<()> = Cmd::quit();
assert!(matches!(cmd.action, Action::Quit));
}
#[test]
fn task_is_dirty() {
let cmd = Cmd::task(async { 42 });
assert!(cmd.dirty);
assert!(matches!(cmd.action, Action::Task(_)));
}
#[test]
fn map_preserves_dirty() {
let cmd: Cmd<i32> = Cmd::dirty();
let mapped: Cmd<String> = cmd.map(|n| n.to_string());
assert!(mapped.dirty);
}
#[test]
fn map_preserves_clean() {
let cmd: Cmd<i32> = Cmd::none();
let mapped: Cmd<String> = cmd.map(|n| n.to_string());
assert!(!mapped.dirty);
}
#[test]
fn batch_is_dirty() {
let cmd: Cmd<i32> = Cmd::batch(vec![Action::None, Action::Quit]);
assert!(cmd.dirty);
assert!(matches!(cmd.action, Action::Batch(_)));
}
}