abacus/abacus-core/src/engine.rs

101 lines
2.4 KiB
Rust

use crate::dataframe;
#[derive(Debug)]
pub struct Engine {
pub blocks: Vec<Block>,
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::<rhai::Dynamic>(&block.script) {
Ok(res) if res.is::<dataframe::DataFrame>() => {
let frame = rhai::Dynamic::cast::<dataframe::DataFrame>(res);
block.output = Output::DataFrame(frame);
}
Ok(res) if res.is::<dataframe::Series>() => {
let frame = rhai::Dynamic::cast::<dataframe::Series>(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()
}
}