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