bundcore 0.7.0

BUND programming language API
Documentation
extern crate log;
use crate::common;
use rust_multistackvm::multistackvm::{VM, StackOps};
use rust_dynamic::types::*;
use easy_error::{Error, bail};

fn get_data_for_stat_from_stack_or_workbench(vm: &mut VM, op: StackOps, err_prefix: String) -> Result<Vec<f64>, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < 1 {
                bail!("Stack is too shallow for inline {}", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.workbench.len() < 1 {
                bail!("Workbench is too shallow for inline {}", &err_prefix);
            }
        }
    }
    let mut res: Vec<f64> = Vec::new();
    match op {
        StackOps::FromStack => {
            loop {
                let value = match vm.stack.pull() {
                    Some(value) => value,
                    None => {
                        break;
                    }
                };
                if value.type_of() == NODATA {
                    break;
                }
                let f_value = match value.conv(FLOAT) {
                    Ok(f_value) => f_value,
                    Err(err) => {
                        bail!("{} returns during conversion: {}", &err_prefix, err);
                    }
                };
                res.push(f_value.cast_float().unwrap());
            }
        }
        StackOps::FromWorkBench => {
            loop {
                let value = match vm.stack.pull_from_workbench() {
                    Some(value) => value,
                    None => {
                        break;
                    }
                };
                if value.type_of() == NODATA {
                    break;
                }
                let f_value = match value.conv(FLOAT) {
                    Ok(f_value) => f_value,
                    Err(err) => {
                        bail!("{} returns during conversion: {}", &err_prefix, err);
                    }
                };
                res.push(f_value.cast_float().unwrap());
            }
        }
    }
    Ok(res)
}

fn get_data_from_metrics(vm: &mut VM, op: StackOps, smode: common::SourceMode, err_prefix: String) -> Result<Vec<f64>, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < 1 {
                bail!("Stack is too shallow for inline {}", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.workbench.len() < 1 {
                bail!("Workbench is too shallow for inline {}", &err_prefix);
            }
        }
    }
    let value = match op {
        StackOps::FromStack => vm.stack.pull(),
        StackOps::FromWorkBench => vm.stack.pull_from_workbench(),
    };
    let metric_value = match value {
        Some(metric_value) => metric_value,
        None => {
            bail!("{} returns NO DATA", &err_prefix);
        }
    };
    if metric_value.type_of() != METRICS {
        bail!("{} did not find a metric type on the stack", &err_prefix);
    }
    let mut res: Vec<f64> = Vec::new();
    match metric_value.cast_metrics() {
        Ok(metrics) => {
            for v in metrics {
                res.push(v.data);
            }
        }
        Err(err) => {
            bail!("{} returns NO METRICS: {}", &err_prefix, err);
        }
    }
    match smode {
        common::SourceMode::Keep => {
            let _ = match op {
                StackOps::FromStack => vm.stack.push(metric_value),
                StackOps::FromWorkBench => vm.stack.push_to_workbench(metric_value),
            };
        }
        _ => {}
    }
    Ok(res)
}

pub fn get_data_from_list(vm: &mut VM, op: StackOps, smode: common::SourceMode, err_prefix: String) -> Result<Vec<f64>, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < 1 {
                bail!("Stack is too shallow for inline {}", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.workbench.len() < 1 {
                bail!("Workbench is too shallow for inline {}", &err_prefix);
            }
        }
    }
    log::debug!("Taking data from stack.");
    let value = match op {
        StackOps::FromStack => vm.stack.pull(),
        StackOps::FromWorkBench => vm.stack.pull_from_workbench(),
    };
    let list_value = match value {
        Some(list_value) => list_value,
        None => {
            bail!("{} returns NO DATA", &err_prefix);
        }
    };
    if list_value.type_of() != LIST {
        bail!("{} did not find a list type on the stack", &err_prefix);
    }
    let mut res: Vec<f64> = Vec::new();
    match list_value.cast_list() {
        Ok(lvalue) => {
            for v in lvalue {
                match v.conv(FLOAT) {
                    Ok(float_value) => {
                        match float_value.cast_float() {
                            Ok(fdata) => {
                                res.push(fdata);
                            }
                            Err(err) => {
                                bail!("{} error FLOAT casting: {}", &err_prefix, err);
                            }
                        }
                    }
                    Err(err) => {
                        bail!("{} error FLOAT conversion: {}", &err_prefix, err);
                    }
                }
            }
        }
        Err(err) => {
            bail!("{} returns NO METRICS: {}", &err_prefix, err);
        }
    }
    match smode {
        common::SourceMode::Keep => {
            log::debug!("Keeping value in the stack by reinserting.");
            let _ = match op {
                StackOps::FromStack => vm.stack.push(list_value),
                StackOps::FromWorkBench => vm.stack.push_to_workbench(list_value),
            };
        }
        _ => {}
    }
    Ok(res)
}

pub fn get_data(vm: &mut VM, op: StackOps, smode: common::SourceMode, err_prefix: String) -> Result<Vec<f64>, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < 1 {
                bail!("Stack is too shallow for inline {}", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.workbench.len() < 1 {
                bail!("Workbench is too shallow for inline {}", &err_prefix);
            }
        }
    }
    let value = match op {
        StackOps::FromStack => vm.stack.peek(),
        StackOps::FromWorkBench => vm.stack.workbench.peek().cloned(),
    };
    match value {
        Some(data_value) => {
            match data_value.type_of() {
                LIST => {
                    log::debug!("Processing data from list.");
                    return get_data_from_list(vm, op, smode, err_prefix);
                }
                METRICS => {
                    log::debug!("Processing data from metrics.");
                    return get_data_from_metrics(vm, op, smode, err_prefix);
                }
                NODATA => bail!("{} END OF DATA", &err_prefix),
                _ => {
                    log::debug!("Processing data from stack.");
                    return get_data_for_stat_from_stack_or_workbench(vm, op, err_prefix);
                }
            }
        }
        None => {
            bail!("{} returns NO DATA", &err_prefix);
        }
    }
}