Abstracting serialization of specific state types

As a first step to someone answering this question, I made your example code readable and compilable (i.e. remove incorrect semicolons and add imports and an fn main, apply rustfmt, add syntax highlighting)

use serde::{Serialize, Deserialize, de::DeserializeOwned};
use serde_json::Result;

pub trait StateTransition<STATE>
where
    STATE: Serialize + DeserializeOwned,
{
    fn act(&self, state: STATE) -> Result<STATE>;
}

fn act_generic<STATE>(state: String, actor: Box<dyn StateTransition<STATE>>) -> Result<String>
where
    STATE: Serialize + DeserializeOwned,
{
    let state: STATE = serde_json::from_str(&state)?;
    let new_state: STATE = actor.act(state)?;
    Ok(serde_json::to_string(&new_state)?)
}

struct StateTransition1 {}
struct StateTransition2 {}

#[derive(Serialize, Deserialize)]
struct State1 {
    x: u32,
}

#[derive(Serialize, Deserialize)]
struct State2 {
    y: u32,
}

impl StateTransition<State1> for StateTransition1 {
    fn act(&self, state: State1) -> Result<State1> {
        Ok(State1 { x: state.x + 1 })
    }
}
impl StateTransition<State2> for StateTransition2 {
    fn act(&self, state: State2) -> Result<State2> {
        Ok(State2 { y: state.y + 2 })
    }
}

fn main() {
    println!(
        "{:?}",
        act_generic(
            r#"{ "x": 1, "y": 2}"#.to_string(),
            Box::new(StateTransition1 {})
        )
    );
    println!(
        "{:?}",
        act_generic(
            r#"{ "x": 1, "y": 2}"#.to_string(),
            Box::new(StateTransition2 {})
        )
    );
}

(playground)

Feel free to read the pinned post about syntax highlighting.

2 Likes