forester_rs/simulator/
builder.rs

1
2use crate::get_pb;
3use crate::runtime::action::keeper::ActionImpl;
4use crate::runtime::builder::ForesterBuilder;
5use crate::runtime::{RtResult, RuntimeError};
6use crate::simulator::actions::SimAction;
7use crate::simulator::config::{SimProfile, TracerSimConfig};
8use crate::simulator::RtAction;
9use crate::simulator::Simulator;
10use crate::tracer::{Tracer, TracerConfig};
11use std::path::PathBuf;
12
13/// The builder to create a simulator process.
14///
15/// # Examples
16/// ```no_run
17/// use std::path::PathBuf;
18/// use forester_rs::runtime::builder::ForesterBuilder;
19/// use forester_rs::simulator::builder::SimulatorBuilder;
20///
21/// fn smoke() {
22///     let mut sb = SimulatorBuilder::new();
23///
24///     let root = PathBuf::from("simulator/smoke");
25///
26///     sb.root(root.clone());
27///     sb.profile(PathBuf::from("sim.yaml"));
28///     
29///     let mut fb = ForesterBuilder::from_fs();
30///
31///     fb.main_file("main.tree".to_string());
32///     fb.root(root);
33///
34///     sb.forester_builder(fb);
35///     
36///     let mut sim = sb.build().unwrap();
37///     sim.run().unwrap();
38/// }
39///
40/// fn smoke_from_text() {
41///     let mut sb = SimulatorBuilder::new();
42///
43///     let sim = PathBuf::from("simulator/smoke/sim.yaml");
44///     let mut fb = ForesterBuilder::from_text();
45///     sb.profile(sim);
46///     
47///     fb.text(
48///         r#"
49/// import "std::actions"
50///
51/// root main sequence {
52///     store("info1", "initial")
53///     retryer(task(config = obj), success())
54///     store("info2","finish")
55/// }
56///
57/// fallback retryer(t:tree, default:tree){
58///     retry(5) t(..)
59///     fail("just should fail")
60///     default(..)
61/// }
62///
63/// impl task(config: object);
64///     "#
65///         .to_string(),
66///     );    
67///     sb.forester_builder(fb);
68///     let mut sim = sb.build().unwrap();
69///     sim.run().unwrap();
70/// }
71/// ```
72#[derive(Default)]
73pub struct SimulatorBuilder {
74    profile: Option<PathBuf>,
75    root: Option<PathBuf>,
76    fb: Option<ForesterBuilder>,
77}
78
79impl SimulatorBuilder {
80    pub fn new() -> Self {
81        SimulatorBuilder {
82            profile: None,
83            fb: None,
84            root: None,
85        }
86    }
87    /// Add a simulator profile.
88    pub fn profile(&mut self, profile: PathBuf) {
89        self.profile = Some(profile);
90    }
91
92    /// Add an ForesterBuilder instance.
93    /// Use `ForesterBuilder` for that.
94    pub fn forester_builder(&mut self, fb: ForesterBuilder) {
95        self.fb = Some(fb);
96    }
97    /// Add the root directory.
98    pub fn root(&mut self, root: PathBuf) {
99        self.root = Some(root);
100    }
101    #[allow(irrefutable_let_patterns)]
102    /// Build
103    pub fn build(&mut self) -> RtResult<Simulator> {
104        let mut fb = self.fb.take().ok_or(RuntimeError::uex(
105            "the forester builder is absent".to_string(),
106        ))?;
107
108        let profile = if let Some(p) = &self.profile {
109            SimProfile::parse_file(&get_pb(p, &self.root.clone())?)?
110        } else {
111            SimProfile::default()
112        };
113
114        let pr = profile.clone();
115
116        if let TracerSimConfig { file, dt_fmt } = profile.config.tracer {
117            let cfg = match file {
118                None => TracerConfig::in_memory(dt_fmt),
119                Some(f) => {
120                    TracerConfig::in_file(get_pb(&PathBuf::from(f), &self.root.clone())?, dt_fmt)
121                }
122            };
123
124            fb.tracer(Tracer::create(cfg)?)
125        }
126
127        if let Some(bb_load_path) = profile.config.bb.load {
128            fb.bb_load(bb_load_path);
129        }
130
131        if let Some(http) = profile.config.http {
132            fb.http_serv(http.port);
133        }
134
135        for action in profile.actions.iter() {
136            let sim_action = SimAction::create(action.stub.as_str(), action.params.clone())?;
137            let name = action.name.as_str();
138
139            if sim_action.is_remote() {
140                fb.register_remote_action(name, sim_action);
141            } else {
142                fb.register_sync_action(name, sim_action);
143            }
144        }
145
146        let forester =
147            fb.build_with(|| ActionImpl::Present(RtAction::sync(SimAction::Success(0))))?;
148        Ok(Simulator::new(self.root.take(), pr, forester))
149    }
150}