From 0e86430ea34fba749c8d7da02f89f1659cc5e264 Mon Sep 17 00:00:00 2001 From: "notryanb@gmail.com" Date: Tue, 8 Oct 2019 22:17:02 -0400 Subject: [PATCH] get very basic average working --- Cargo.toml | 4 ++ src/plugins/average.rs | 106 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/plugins/average.rs diff --git a/Cargo.toml b/Cargo.toml index cd6be5d9fa..16b8c85863 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,6 +119,10 @@ path = "src/plugins/inc.rs" name = "nu_plugin_sum" path = "src/plugins/sum.rs" +[[bin]] +name = "nu_plugin_average" +path = "src/plugins/average.rs" + [[bin]] name = "nu_plugin_embed" path = "src/plugins/embed.rs" diff --git a/src/plugins/average.rs b/src/plugins/average.rs new file mode 100644 index 0000000000..5e76560d40 --- /dev/null +++ b/src/plugins/average.rs @@ -0,0 +1,106 @@ +use nu::{ + serve_plugin, CoerceInto, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, + Tagged, TaggedItem, Value, +}; + +#[derive(Debug)] +struct Average { + total: Option>, + count: u64, +} + +impl Average { + fn new() -> Average { + Average { total: None, count: 1 } + } + + fn average(&mut self, value: Tagged) -> Result<(), ShellError> { + match value.item() { + Value::Primitive(Primitive::Nothing) => Ok(()), + Value::Primitive(Primitive::Int(i)) => { + match &self.total { + Some(Tagged { + item: Value::Primitive(Primitive::Int(j)), + tag, + }) => { + self.total = Some(Value::int(i + j).tagged(tag)); + self.count = self.count + 1; + Ok(()) + } + None => { + self.total = Some(value.clone()); + Ok(()) + } + _ => Err(ShellError::string(format!( + "Could not calculate average of non-integer or unrelated types" + ))), + } + } + Value::Primitive(Primitive::Bytes(b)) => { + match self.total { + Some(Tagged { + item: Value::Primitive(Primitive::Bytes(j)), + tag, + }) => { + self.total = Some(Value::int(b + j).tagged(tag)); + self.count = self.count + 1; + Ok(()) + } + None => { + self.total = Some(value); + Ok(()) + } + _ => Err(ShellError::string(format!( + "Could not calculate average of non-integer or unrelated types" + ))), + } + } + x => Err(ShellError::string(format!( + "Unrecognized type in stream: {:?}", + x + ))), + } + + } +} + +impl Plugin for Average { + fn config(&mut self) -> Result { + Ok(Signature::build("average") + .desc("Compute the average of a column of numerical values.") + .filter()) + } + + fn begin_filter(&mut self, _: CallInfo) -> Result, ShellError> { + Ok(vec![]) + } + + fn filter(&mut self, input: Tagged) -> Result, ShellError> { + self.average(input)?; + Ok(vec![]) + } + + fn end_filter(&mut self) -> Result, ShellError> { + match self.total { + None => Ok(vec![]), + Some(ref v) => { + match v.item() { + Value::Primitive(Primitive::Int(i)) => { + let total: u64 = i.tagged(v.tag).coerce_into("converting for average")?; + let avg = total as f64 / self.count as f64; + let decimal_value: Value= Primitive::from(avg).into(); + let tagged_value = decimal_value.tagged(v.tag); + Ok(vec![ReturnSuccess::value(tagged_value)]) + } + _ => unreachable!() + + } + }, + } + } +} + +fn main() { + serve_plugin(&mut Average::new()); +} +