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
use super::{ sink_names_a_b, source_names_output, BinBuildEnvironment, BinDescription, Calculator, FetchItem, GetCalibration, Item, Iteration, Result, Scope, SinkBin, SinkNames, SourceBin, SourceId, SourceNames, SourceSinkBinDescription, WriteDotSimple, SINK_A, SINK_B, SOURCE_OUTPUT, }; use crate::error; use crate::item::TwoItemsExt; use indexmap::IndexSet; use std; static BIN_TYPE: &'static str = "add"; pub struct Bin { scope: Scope, source_a: Box<FetchItem>, source_b: Box<FetchItem>, result_output: Item, } impl SinkBin for Bin {} impl SourceBin for Bin { fn get_source_data(&self, source: &SourceId) -> Result<Item> { if source.id == SOURCE_OUTPUT { Ok(self.result_output.clone()) } else { error::MissingSourceName { scope: self.scope.clone(), name: source.id.to_string(), bin_type: BIN_TYPE.to_string(), } .fail() } } } impl Calculator for Bin { fn calculate(&mut self, _iteration: &Iteration) -> Result<()> { let a = self.source_a.fetch_item(&self.scope)?; let b = self.source_b.fetch_item(&self.scope)?; self.result_output = match (a, b).common_type() { (Item::I8(a), Item::I8(b)) => logic(a, b), (Item::I16(a), Item::I16(b)) => logic(a, b), (Item::I32(a), Item::I32(b)) => logic(a, b), (Item::I64(a), Item::I64(b)) => logic(a, b), (Item::U8(a), Item::U8(b)) => logic(a, b), (Item::U16(a), Item::U16(b)) => logic(a, b), (Item::U32(a), Item::U32(b)) => logic(a, b), (Item::U64(a), Item::U64(b)) => logic(a, b), (Item::F32(a), Item::F32(b)) => logic(a, b), (Item::F64(a), Item::F64(b)) => logic(a, b), _ => Item::Nothing, }; Ok(()) } } fn logic<T: std::ops::Add + Into<Item>>(a: T, b: T) -> Item where T: std::ops::Add, Item: std::convert::From<<T as std::ops::Add>::Output>, { (a + b).into() } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Description; impl BinDescription for Description { type Bin = Bin; fn check_validity( &self, _scope: &Scope, _get_calibration: &mut GetCalibration, ) -> Result<()> { Ok(()) } fn bin_type(&self) -> &'static str { BIN_TYPE } } impl SourceNames for Description { fn source_names(&self) -> Result<IndexSet<String>> { Ok(source_names_output()) } } impl SinkNames for Description { fn sink_names(&self) -> IndexSet<String> { sink_names_a_b() } } impl SourceSinkBinDescription for Description { fn build_bin( &self, scope: &Scope, env: &mut BinBuildEnvironment, ) -> Result<Self::Bin> { Ok(Bin { scope: scope.clone(), source_a: env.resolve(SINK_A)?, source_b: env.resolve(SINK_B)?, result_output: Item::Nothing, }) } } impl WriteDotSimple for Description {}