pub struct Decider<'a, C: 'a, S: 'a, E: 'a, Error: 'a = ()> {
pub decide: DecideFunction<'a, C, S, E, Error>,
pub evolve: EvolveFunction<'a, S, E>,
pub initial_state: InitialStateFunction<'a, S>,
}
Expand description
Decider represents the main decision-making algorithm.
It has three generic parameters C
/Command
, S
/State
, E
/Event
, representing the type of the values that Decider may contain or use.
'a
is used as a lifetime parameter, indicating that all references contained within the struct (e.g., references within the function closures) must have a lifetime that is at least as long as ’a.
§Example
use fmodel_rust::decider::{Decider, EventComputation, StateComputation};
fn decider<'a>() -> Decider<'a, OrderCommand, OrderState, OrderEvent> {
Decider {
// Exhaustive pattern matching is used to handle the commands (modeled as Enum - SUM/OR type).
decide: Box::new(|command, state| {
match command {
OrderCommand::Create(create_cmd) => {
Ok(vec![OrderEvent::Created(OrderCreatedEvent {
order_id: create_cmd.order_id,
customer_name: create_cmd.customer_name.to_owned(),
items: create_cmd.items.to_owned(),
})])
}
OrderCommand::Update(update_cmd) => {
if state.order_id == update_cmd.order_id {
Ok(vec![OrderEvent::Updated(OrderUpdatedEvent {
order_id: update_cmd.order_id,
updated_items: update_cmd.new_items.to_owned(),
})])
} else {
Ok(vec![])
}
}
OrderCommand::Cancel(cancel_cmd) => {
if state.order_id == cancel_cmd.order_id {
Ok(vec![OrderEvent::Cancelled(OrderCancelledEvent {
order_id: cancel_cmd.order_id,
})])
} else {
Ok(vec![])
}
}
}
}),
// Exhaustive pattern matching is used to handle the events (modeled as Enum - SUM/OR type).
evolve: Box::new(|state, event| {
let mut new_state = state.clone();
match event {
OrderEvent::Created(created_event) => {
new_state.order_id = created_event.order_id;
new_state.customer_name = created_event.customer_name.to_owned();
new_state.items = created_event.items.to_owned();
}
OrderEvent::Updated(updated_event) => {
new_state.items = updated_event.updated_items.to_owned();
}
OrderEvent::Cancelled(_) => {
new_state.is_cancelled = true;
}
}
new_state
}),
initial_state: Box::new(|| OrderState {
order_id: 0,
customer_name: "".to_string(),
items: Vec::new(),
is_cancelled: false,
}),
}
}
// Modeling the commands, events, and state. Enum is modeling the SUM/OR type, and struct is modeling the PRODUCT/AND type.
#[derive(Debug)]
pub enum OrderCommand {
Create(CreateOrderCommand),
Update(UpdateOrderCommand),
Cancel(CancelOrderCommand),
}
#[derive(Debug)]
pub struct CreateOrderCommand {
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
}
#[derive(Debug)]
pub struct UpdateOrderCommand {
pub order_id: u32,
pub new_items: Vec<String>,
}
#[derive(Debug)]
pub struct CancelOrderCommand {
pub order_id: u32,
}
#[derive(Debug, PartialEq)]
pub enum OrderEvent {
Created(OrderCreatedEvent),
Updated(OrderUpdatedEvent),
Cancelled(OrderCancelledEvent),
}
#[derive(Debug, PartialEq)]
pub struct OrderCreatedEvent {
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
}
#[derive(Debug, PartialEq)]
pub struct OrderUpdatedEvent {
pub order_id: u32,
pub updated_items: Vec<String>,
}
#[derive(Debug, PartialEq)]
pub struct OrderCancelledEvent {
pub order_id: u32,
}
#[derive(Debug, Clone, PartialEq)]
struct OrderState {
order_id: u32,
customer_name: String,
items: Vec<String>,
is_cancelled: bool,
}
let decider: Decider<OrderCommand, OrderState, OrderEvent> = decider();
let create_order_command = OrderCommand::Create(CreateOrderCommand {
order_id: 1,
customer_name: "John Doe".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
});
let new_events = decider.compute_new_events(&[], &create_order_command);
assert_eq!(new_events, Ok(vec![OrderEvent::Created(OrderCreatedEvent {
order_id: 1,
customer_name: "John Doe".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
})]));
let new_state = decider.compute_new_state(None, &create_order_command);
assert_eq!(new_state, Ok(OrderState {
order_id: 1,
customer_name: "John Doe".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
is_cancelled: false,
}));
Fields§
§decide: DecideFunction<'a, C, S, E, Error>
The decide
function is used to decide which events to produce based on the command and the current state.
evolve: EvolveFunction<'a, S, E>
The evolve
function is used to evolve the state based on the current state and the event.
initial_state: InitialStateFunction<'a, S>
The initial_state
function is used to produce the initial state of the decider.
Implementations§
Source§impl<'a, C, S, E, Error> Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error> Decider<'a, C, S, E, Error>
Sourcepub fn map_state<S2, F1, F2>(
self,
f1: F1,
f2: F2,
) -> Decider<'a, C, S2, E, Error>
pub fn map_state<S2, F1, F2>( self, f1: F1, f2: F2, ) -> Decider<'a, C, S2, E, Error>
Maps the Decider over the S/State type parameter.
Creates a new instance of Decider<C, S2, E, Error>
.
Sourcepub fn map_event<E2, F1, F2>(
self,
f1: F1,
f2: F2,
) -> Decider<'a, C, S, E2, Error>
pub fn map_event<E2, F1, F2>( self, f1: F1, f2: F2, ) -> Decider<'a, C, S, E2, Error>
Maps the Decider over the E/Event type parameter.
Creates a new instance of Decider<C, S, E2, Error>
.
Sourcepub fn map_command<C2, F>(self, f: F) -> Decider<'a, C2, S, E, Error>
pub fn map_command<C2, F>(self, f: F) -> Decider<'a, C2, S, E, Error>
Maps the Decider over the C/Command type parameter.
Creates a new instance of Decider<C2, S, E, Error>
.
Sourcepub fn map_error<Error2, F>(self, f: F) -> Decider<'a, C, S, E, Error2>
pub fn map_error<Error2, F>(self, f: F) -> Decider<'a, C, S, E, Error2>
Maps the Decider over the Error type parameter.
Creates a new instance of Decider<C, S, E, Error2>
.
Sourcepub fn combine<C2, S2, E2>(
self,
decider2: Decider<'a, C2, S2, E2, Error>,
) -> Decider<'a, Sum<C, C2>, (S, S2), Sum<E, E2>, Error>
pub fn combine<C2, S2, E2>( self, decider2: Decider<'a, C2, S2, E2, Error>, ) -> Decider<'a, Sum<C, C2>, (S, S2), Sum<E, E2>, Error>
Combines two deciders into one bigger decider
Creates a new instance of a Decider by combining two deciders of type C
, S
, E
and C2
, S2
, E2
into a new decider of type Sum<C, C2>
, (S, S2)
, Sum<E, E2>
Sourcepub fn combine3<C2, S2, E2, C3, S3, E3>(
self,
decider2: Decider<'a, C2, S2, E2, Error>,
decider3: Decider<'a, C3, S3, E3, Error>,
) -> Decider<'a, Sum3<C, C2, C3>, (S, S2, S3), Sum3<E, E2, E3>, Error>
pub fn combine3<C2, S2, E2, C3, S3, E3>( self, decider2: Decider<'a, C2, S2, E2, Error>, decider3: Decider<'a, C3, S3, E3, Error>, ) -> Decider<'a, Sum3<C, C2, C3>, (S, S2, S3), Sum3<E, E2, E3>, Error>
Combines three deciders into one bigger decider
Sourcepub fn combine4<C2, S2, E2, C3, S3, E3, C4, S4, E4>(
self,
decider2: Decider<'a, C2, S2, E2, Error>,
decider3: Decider<'a, C3, S3, E3, Error>,
decider4: Decider<'a, C4, S4, E4, Error>,
) -> Decider<'a, Sum4<C, C2, C3, C4>, (S, S2, S3, S4), Sum4<E, E2, E3, E4>, Error>
pub fn combine4<C2, S2, E2, C3, S3, E3, C4, S4, E4>( self, decider2: Decider<'a, C2, S2, E2, Error>, decider3: Decider<'a, C3, S3, E3, Error>, decider4: Decider<'a, C4, S4, E4, Error>, ) -> Decider<'a, Sum4<C, C2, C3, C4>, (S, S2, S3, S4), Sum4<E, E2, E3, E4>, Error>
Combines four deciders into one bigger decider
Sourcepub fn combine5<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5>(
self,
decider2: Decider<'a, C2, S2, E2, Error>,
decider3: Decider<'a, C3, S3, E3, Error>,
decider4: Decider<'a, C4, S4, E4, Error>,
decider5: Decider<'a, C5, S5, E5, Error>,
) -> Decider<'a, Sum5<C, C2, C3, C4, C5>, (S, S2, S3, S4, S5), Sum5<E, E2, E3, E4, E5>, Error>
pub fn combine5<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5>( self, decider2: Decider<'a, C2, S2, E2, Error>, decider3: Decider<'a, C3, S3, E3, Error>, decider4: Decider<'a, C4, S4, E4, Error>, decider5: Decider<'a, C5, S5, E5, Error>, ) -> Decider<'a, Sum5<C, C2, C3, C4, C5>, (S, S2, S3, S4, S5), Sum5<E, E2, E3, E4, E5>, Error>
Combines five deciders into one bigger decider
Sourcepub fn combine6<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5, C6, S6, E6>(
self,
decider2: Decider<'a, C2, S2, E2, Error>,
decider3: Decider<'a, C3, S3, E3, Error>,
decider4: Decider<'a, C4, S4, E4, Error>,
decider5: Decider<'a, C5, S5, E5, Error>,
decider6: Decider<'a, C6, S6, E6, Error>,
) -> Decider<'a, Sum6<C, C2, C3, C4, C5, C6>, (S, S2, S3, S4, S5, S6), Sum6<E, E2, E3, E4, E5, E6>, Error>
pub fn combine6<C2, S2, E2, C3, S3, E3, C4, S4, E4, C5, S5, E5, C6, S6, E6>( self, decider2: Decider<'a, C2, S2, E2, Error>, decider3: Decider<'a, C3, S3, E3, Error>, decider4: Decider<'a, C4, S4, E4, Error>, decider5: Decider<'a, C5, S5, E5, Error>, decider6: Decider<'a, C6, S6, E6, Error>, ) -> Decider<'a, Sum6<C, C2, C3, C4, C5, C6>, (S, S2, S3, S4, S5, S6), Sum6<E, E2, E3, E4, E5, E6>, Error>
Combines six deciders into one bigger decider
Trait Implementations§
Source§impl<C, S, E, Error> EventComputation<C, S, E, Error> for Decider<'_, C, S, E, Error>
impl<C, S, E, Error> EventComputation<C, S, E, Error> for Decider<'_, C, S, E, Error>
Source§impl<C, S, E, Error> StateComputation<C, S, E, Error> for Decider<'_, C, S, E, Error>
impl<C, S, E, Error> StateComputation<C, S, E, Error> for Decider<'_, C, S, E, Error>
Auto Trait Implementations§
impl<'a, C, S, E, Error> Freeze for Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error = ()> !RefUnwindSafe for Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error> Send for Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error> Sync for Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error> Unpin for Decider<'a, C, S, E, Error>
impl<'a, C, S, E, Error = ()> !UnwindSafe for Decider<'a, C, S, E, Error>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the foreground set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red()
and
green()
, which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg()
:
use yansi::{Paint, Color};
painted.fg(Color::White);
Set foreground color to white using white()
.
use yansi::Paint;
painted.white();
Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the background set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red()
and
on_green()
, which have the same functionality but
are pithier.
§Example
Set background color to red using fg()
:
use yansi::{Paint, Color};
painted.bg(Color::Red);
Set background color to red using on_red()
.
use yansi::Paint;
painted.on_red();
Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute
value
.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold()
and
underline()
, which have the same functionality
but are pithier.
§Example
Make text bold using attr()
:
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);
Make text bold using using bold()
.
use yansi::Paint;
painted.bold();
Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi
Quirk
value
.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask()
and
wrap()
, which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk()
:
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);
Enable wrapping using wrap()
.
use yansi::Paint;
painted.wrap();
Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition
value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted
only when both stdout
and stderr
are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);