stepflow_serde/
session.rs

1use std::collections::HashMap;
2use serde::{Deserialize};
3use stepflow::prelude::*;
4use stepflow::object::IdError;
5use stepflow::{Session, SessionId, Error};
6
7use super::{VarSerde, StepSerde, ActionSerde, SerdeError};
8
9
10// we reserve anything with prefixed with a $.. maybe someday we'll enforce it.
11const NAME_GLOBAL_ACTION: &str = "$all";
12const NAME_ROOT_STEP: &str = "$root";
13
14
15#[derive(Debug, Deserialize)]
16#[serde(rename = "Session")]
17pub struct SessionSerde {
18    vars: Option<HashMap<String, VarSerde>>,
19    steps: HashMap<String, StepSerde>,
20    actions: HashMap<String, ActionSerde>,
21}
22
23impl SessionSerde {
24    /// Converts into a [`Session`]
25    ///
26    /// if `allow_implicit_var` is `true`, when a [`Step`](stepflow::step::Step) is parsed and uses a variable that has
27    /// not been declared in the `vars` section, a [`StringVar`](stepflow::data::StringVar) will be created.
28    pub fn into_session<T>(self, session_id: SessionId, allow_implicit_var: bool) -> Result<Session, SerdeError<T>> {
29        let mut session = Session::with_capacity(
30            session_id,
31            if let Some(vars) = &self.vars { vars.len() } else { 0 },
32            self.steps.len(),
33            self.actions.len()
34        );
35
36        // Create Vars
37        if let Some(vars) = self.vars {
38            for (var_name, var_serde) in vars {
39                session.var_store_mut().insert_new_named(var_name, |var_id| {
40                    Ok(var_serde.to_var(var_id))
41                })?;
42            }
43        }
44
45        // Create implicit vars from Steps
46        if allow_implicit_var {
47            for (_step_name, step_serde) in &self.steps {
48                step_serde.ensure_all_vars(&mut session)?;
49            }
50        }
51
52        // Create Steps
53        // steps in 2 passes.
54        // 1. register just the steps, no sub-steps since it's possible they'll be registered later
55        // 2. once all the steps are registered, assign the child sub-steps
56        let mut stepid_to_substep_names = HashMap::with_capacity(self.steps.len());
57        for (step_name, step_serde) in self.steps {
58            let var_store = session.var_store();
59            
60            let input_var_ids = step_serde.input_var_ids(var_store)?;
61            let output_var_ids = step_serde.output_var_ids(var_store)?;
62
63            session.step_store_mut().insert_new_named(step_name, |step_id| {
64                let (step, substep_names) = step_serde.to_step(step_id, input_var_ids, output_var_ids)?;
65                stepid_to_substep_names.insert(step.id().clone(), substep_names);
66                Ok(step)
67            })?;
68        }
69        for (step_id, substep_names) in stepid_to_substep_names {
70            if let Some(substep_names) = substep_names {
71                StepSerde::add_substeps(step_id, substep_names, session.step_store_mut())?;
72            }
73        }
74
75        // Set Root Step
76        let root_step_id = session.step_store()
77            .id_from_name(NAME_ROOT_STEP)
78            .ok_or_else(|| Error::StepId(IdError::NoSuchName(NAME_ROOT_STEP.to_owned())))?.clone();
79        session.push_root_substep(root_step_id);
80
81        // Set actions
82        for (step_name, action_serde) in self.actions {
83            let action_id = session.action_store_mut().reserve_id();
84            let action = action_serde.to_action(action_id, session.var_store())?;
85            session.action_store_mut().register_named::<String>(step_name.clone(), action)?;
86            if step_name.eq(NAME_GLOBAL_ACTION) {
87                session.set_action_for_step(action_id, None)?;
88            } else {
89                let step_id = session.step_store().id_from_name(&step_name[..]).ok_or_else(|| Error::StepId(IdError::NoSuchName(step_name)))?.clone();
90                session.set_action_for_step(action_id, Some(&step_id))?;
91            }
92        }
93
94        // Return session
95        Ok(session)
96    }
97}