use super::{
BinBuildEnvironment, BinDescription, Calculator, FetchItem,
GetCalibration, Item, Iteration, Result, Scope, SinkBin, SinkNames,
SourceBin, SourceId, SourceNames, SourceSinkBinDescription,
WriteDotSimple,
};
use crate::error;
use indexmap::{IndexMap, IndexSet};
use snafu::OptionExt;
static BIN_TYPE: &str = "passthrough";
#[derive(Debug)]
pub struct Bin {
scope: Scope,
inputs: IndexMap<String, Box<dyn FetchItem>>,
outputs: IndexMap<String, Item>,
}
impl SinkBin for Bin {}
impl SourceBin for Bin {
fn get_source_data(&self, source: &SourceId) -> Result<Item> {
self.outputs
.get(&source.id)
.context(error::MissingSourceName {
scope: self.scope.clone(),
name: source.id.to_string(),
bin_type: BIN_TYPE.to_string(),
})
.map(Clone::clone)
}
}
impl Calculator for Bin {
fn calculate(&mut self, _iteration: &Iteration) -> Result<()> {
self.outputs = self
.inputs
.iter()
.map(|(s, ds)| {
ds.fetch_item(&self.scope).map(|d| (s.to_string(), d))
})
.collect::<Result<IndexMap<String, Item>>>()?;
Ok(())
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Description {
pub inputs: IndexSet<String>,
}
impl BinDescription for Description {
type Bin = Bin;
fn check_validity(
&self,
_scope: &Scope,
_get_calibration: &mut dyn GetCalibration,
) -> Result<()> {
Ok(())
}
fn bin_type(&self) -> &'static str {
BIN_TYPE
}
}
impl SinkNames for Description {
fn sink_names(&self) -> IndexSet<String> {
self.inputs.clone()
}
}
impl SourceNames for Description {
fn source_names(&self) -> Result<IndexSet<String>> {
Ok(self.inputs.clone())
}
}
impl SourceSinkBinDescription for Description {
fn build_bin(
&self,
scope: &Scope,
env: &mut dyn BinBuildEnvironment,
) -> Result<Self::Bin> {
let inputs = self
.inputs
.iter()
.map(|input| {
env.resolve(input).map(|sink| (input.to_string(), sink))
})
.collect::<Result<IndexMap<String, Box<dyn FetchItem>>>>()?;
let outputs = self
.inputs
.iter()
.map(|k| (k.to_string(), Item::Nothing))
.collect();
Ok(Bin {
scope: scope.clone(),
inputs,
outputs,
})
}
}
impl WriteDotSimple for Description {}
#[cfg(test)]
mod tests {
use super::Description;
use crate::bins::{directsource, verificationsink};
use crate::Item as I;
use crate::{run_bin, Result};
use indexmap::indexset;
#[test]
fn simulate() -> Result<()> {
use crate::Item::*;
let rows = vec![
vec![Nothing, Nothing],
vec![Nothing, I::from(1f64)],
vec![I::from(1f64), Nothing],
vec![I::from(1f64), I::from(1f64)],
vec![I::from(0f64), I::from(1f64)],
vec![I::from(1f64), I::from(0f64)],
vec![I::from(0f64), I::from(0f64)],
vec![I::from(2f64), I::from(0f64)],
vec![I::from(1f64), I::from(2f64)],
vec![I::from(2f64), I::from(1f64)],
vec![I::from(2f64), I::from(2f64)],
];
let input = directsource::Description {
columns: indexset!["a".to_string(), "b".to_string()],
rows: rows.clone().into(),
};
let verification = verificationsink::Description {
columns: indexset!["a".to_string(), "b".to_string()],
expected: rows.clone().into(),
};
run_bin(
&input,
&Description {
inputs: indexset! {"a".to_string(),"b".to_string()},
},
&verification,
)
}
}