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
extern crate serde_cbor; use super::{ BinBuildEnvironment, BinDescription, Calculator, FetchItem, GetCalibration, Item, Iteration, Result, Scope, SinkBin, SinkNames, SinkOnlyBin, SinkOnlyBinDescription, }; use crate::error; use indexmap::{IndexMap, IndexSet}; use snafu::ResultExt; use std; use std::fs::File; use std::io::{LineWriter, Write}; static BIN_TYPE: &'static str = "cborsink"; pub struct Bin { scope: Scope, writer: Box<Write>, sources: IndexMap<String, Box<FetchItem>>, } impl SinkBin for Bin {} impl Calculator for Bin { fn calculate(&mut self, _iteration: &Iteration) -> Result<()> { let items = self .sources .iter() .map(|(s, ds)| { ds.fetch_item(&self.scope).map(|d| (s.to_string(), d)) }) .collect::<Result<IndexMap<String, Item>>>()?; serde_cbor::to_writer( &mut self.writer, &items.values().collect::<Vec<_>>(), ) .context(error::SerdeCbor)?; Ok(()) } } impl SinkOnlyBin for Bin {} #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Description { pub sinks: IndexSet<String>, #[serde(default, skip_serializing_if = "Option::is_none")] pub file_path: Option<String>, } 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 SinkNames for Description { fn sink_names(&self) -> IndexSet<String> { self.sinks.clone() } } impl SinkOnlyBinDescription for Description { fn build_bin( &self, scope: &Scope, env: &mut BinBuildEnvironment, ) -> Result<Self::Bin> { let mut writer: Box<Write> = if let Some(ref path) = self.file_path { let file = File::create(&path.to_string()).context(error::Io)?; Box::new(LineWriter::new(file)) } else { Box::new(LineWriter::new(std::io::stdout())) }; serde_cbor::to_writer(&mut writer, &self.sinks) .context(error::SerdeCbor)?; Ok(Bin { scope: scope.clone(), writer, sources: self .sinks .iter() .map(|s| env.resolve(s).map(|ds| (s.to_string(), ds))) .collect::<Result<IndexMap<_, _>>>()?, }) } }