-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(state): accepting arbitrary N-state and N-context definitons
- Loading branch information
Showing
4 changed files
with
158 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,53 @@ | ||
use anyhow::{anyhow, Error}; | ||
use serde::{Deserialize, Serialize}; | ||
use serde_json::{json, Value}; | ||
|
||
pub trait Context { | ||
fn read<T: for<'de> Deserialize<'de>>(&self) -> Result<T, Error>; | ||
fn write<T: Serialize>(&mut self, data: &T) -> Result<(), Error>; | ||
fn read_input(&self) -> Result<Value, Error>; | ||
fn write_output(&mut self, data: &Value) -> Result<(), Error>; | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct RawContext { | ||
data: String, | ||
// Your custom context that implements the library's Context trait. | ||
pub struct MyContext { | ||
data: Value, | ||
} | ||
|
||
impl RawContext { | ||
impl MyContext { | ||
pub fn new() -> Self { | ||
Self { | ||
data: "{}".to_string(), | ||
} | ||
Self { data: json!({}) } | ||
} | ||
} | ||
|
||
impl Context for RawContext { | ||
fn read<T: for<'de> Deserialize<'de>>(&self) -> Result<T, Error> { | ||
serde_json::from_str(&self.data).map_err(|e| anyhow!("error on deserialize: {}", e)) | ||
impl Context for MyContext { | ||
fn read_input(&self) -> Result<Value, Error> { | ||
Ok(self.data.clone()) | ||
} | ||
|
||
fn write<T: Serialize>(&mut self, data: &T) -> Result<(), Error> { | ||
self.data = serde_json::to_string(data)?; | ||
fn write_output(&mut self, data: &Value) -> Result<(), Error> { | ||
self.data = data.clone(); | ||
Ok(()) | ||
} | ||
} | ||
|
||
// #[derive(Debug)] | ||
// pub struct RawContext { | ||
// data: String, | ||
// } | ||
// | ||
// impl RawContext { | ||
// pub fn new() -> Self { | ||
// Self { | ||
// data: "{}".to_string(), | ||
// } | ||
// } | ||
// } | ||
// | ||
// impl Context for RawContext { | ||
// fn read<T: for<'de> Deserialize<'de>>(&self) -> Result<T, Error> { | ||
// serde_json::from_str(&self.data).map_err(|e| anyhow!("error on deserialize: {}", e)) | ||
// } | ||
// | ||
// fn write<T: Serialize>(&mut self, data: &T) -> Result<(), Error> { | ||
// self.data = serde_json::to_string(data)?; | ||
// Ok(()) | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,2 @@ | ||
use anyhow::Error; | ||
use mfm_machine_macros::StateConfigReqs; | ||
use serde_derive::{Deserialize, Serialize}; | ||
|
||
use crate::state::{context::Context, DependencyStrategy, Label, StateConfig, StateHandler, Tag}; | ||
|
||
#[derive(Debug, Clone, PartialEq, StateConfigReqs)] | ||
pub struct Setup { | ||
label: Label, | ||
tags: Vec<Tag>, | ||
depends_on: Vec<Tag>, | ||
depends_on_strategy: DependencyStrategy, | ||
} | ||
|
||
impl Setup { | ||
pub fn new() -> Self { | ||
Self { | ||
label: Label::new("setup_state").unwrap(), | ||
tags: vec![Tag::new("setup").unwrap()], | ||
depends_on: vec![Tag::new("setup").unwrap()], | ||
depends_on_strategy: DependencyStrategy::Latest, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize, Serialize)] | ||
struct SetupStateData {} | ||
|
||
impl StateHandler for Setup { | ||
fn handler<C: Context>(&self, context: &mut C) -> Result<(), Error> { | ||
let _data: SetupStateData = context.read().unwrap(); | ||
let data = "some new data".to_string(); | ||
context.write(&data) | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, StateConfigReqs)] | ||
pub struct Report { | ||
label: Label, | ||
tags: Vec<Tag>, | ||
depends_on: Vec<Tag>, | ||
depends_on_strategy: DependencyStrategy, | ||
} | ||
|
||
impl Report { | ||
pub fn new() -> Self { | ||
Self { | ||
label: Label::new("report_state").unwrap(), | ||
tags: vec![Tag::new("report").unwrap()], | ||
depends_on: vec![Tag::new("setup").unwrap()], | ||
depends_on_strategy: DependencyStrategy::Latest, | ||
} | ||
} | ||
} | ||
|
||
impl StateHandler for Report { | ||
fn handler<C: Context>(&self, context: &mut C) -> Result<(), Error> { | ||
let _data: String = context.read().unwrap(); | ||
let data = "some new data reported".to_string(); | ||
context.write(&data) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use crate::state::{context::RawContext, State, StateWrapper}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_setup_state_initialization() { | ||
let label = Label::new("setup_state").unwrap(); | ||
let tags = vec![Tag::new("setup").unwrap()]; | ||
let state = State::Setup(StateWrapper::new(Setup::new())); | ||
let mut ctx_input = RawContext::new(); | ||
match state { | ||
State::Setup(t) => { | ||
let result = t.handler(&mut ctx_input); | ||
assert!(result.is_ok()); | ||
assert_eq!(t.label(), &label); | ||
assert_eq!(t.tags(), &tags); | ||
} | ||
_ => panic!("expected Setup state"), | ||
} | ||
} | ||
} |