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
extern crate serde; extern crate serde_json; use snafu::{ensure, OptionExt}; use super::{ BinDescription, GetCalibration, Item, Iteration, Proceed, Result, Scope, SourceBin, SourceId, SourceNames, SourceOnlyBin, SourceOnlyBinDescription, }; use crate::error; use indexmap::IndexSet; use std::collections::VecDeque; static BIN_TYPE: &'static str = "directsource"; #[derive(Debug)] pub struct Bin { scope: Scope, columns: IndexSet<String>, rows: VecDeque<Vec<Item>>, outputs: Vec<Item>, } impl SourceOnlyBin for Bin { fn fetch_next(&mut self, _iteration: &Iteration) -> Result<Proceed> { if let Some(row) = self.rows.pop_front() { self.outputs = row; Ok(Proceed::Continue) } else { Ok(Proceed::Stop) } } } impl SourceBin for Bin { fn get_source_data(&self, source: &SourceId) -> Result<Item> { let index = self.columns.iter().position(|s| s == &source.id); let index = index.context(error::InvalidSourceName { scope: self.scope.clone(), name: source.id.to_string(), bin_type: BIN_TYPE.to_string(), })?; Ok(self.outputs.get(index).cloned().unwrap()) } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Description { pub columns: IndexSet<String>, pub rows: VecDeque<Vec<Item>>, } impl BinDescription for Description { type Bin = Bin; fn check_validity( &self, _scope: &Scope, _get_calibration: &mut GetCalibration, ) -> Result<()> { ensure!(!self.columns.is_empty(), error::InvalidDirectSourceData); ensure!( self.columns.iter().collect::<IndexSet<_>>().len() == self.columns.len(), error::InvalidDirectSourceData ); for row in &self.rows { ensure!( row.len() == self.columns.len(), error::InvalidDirectSourceData ); } Ok(()) } fn bin_type(&self) -> &'static str { BIN_TYPE } } impl SourceNames for Description { fn source_names(&self) -> Result<IndexSet<String>> { Ok(self.columns.clone()) } } impl SourceOnlyBinDescription for Description { fn build_bin(&self, scope: &Scope) -> Result<Self::Bin> { Ok(Bin { scope: scope.clone(), columns: self.columns.clone(), rows: self.rows.clone(), outputs: self.columns.iter().map(|_| Item::Nothing).collect(), }) } }