use crate::dataframe; #[derive(Debug)] pub struct Engine { pub blocks: Vec, engine: rhai::Engine, } impl Default for Engine { fn default() -> Self { let mut engine = rhai::Engine::new(); engine.set_fast_operators(false); dataframe::setup_engine(&mut engine); Self { engine, blocks: vec![Block::default()], } } } impl Engine { pub fn process(&mut self) { for block in self.blocks.iter_mut() { match self.engine.eval::(&block.script) { Ok(res) if res.is::() => { let frame = rhai::Dynamic::cast::(res); block.output = Output::DataFrame(frame); } Ok(res) if res.is::() => { let frame = rhai::Dynamic::cast::(res); block.output = Output::Series(frame); } Ok(res) => { block.output = Output::Scalar(res); } Err(e) => { block.output = Output::Error(e.to_string()); } } } } } #[derive(Debug, Clone)] pub enum Output { None, Scalar(rhai::Dynamic), DataFrame(dataframe::DataFrame), Series(dataframe::Series), Error(String), } impl Output { pub fn into_frame(self) -> dataframe::DataFrame { if let Self::DataFrame(v) = self { return v; } panic!("Not a dataframe"); } pub fn into_series(self) -> dataframe::Series { if let Self::Series(v) = self { return v; } panic!("Not a series"); } pub fn into_scalar(self) -> rhai::Dynamic { if let Self::Scalar(v) = self { return v; } panic!("Not a scalar"); } } #[derive(Debug)] pub struct Block { pub script: String, pub output: Output, } impl Default for Block { fn default() -> Self { Self { script: Default::default(), output: Output::None, } } } #[cfg(test)] pub mod tests { use super::*; pub fn process(script: &str) -> Output { let mut engine = Engine::default(); engine.blocks[0].script = script.into(); engine.process(); engine.blocks[0].output.clone() } }