Deserialization and outputstream math commands (#3315)

* Output error when ls into a file without permission

* math sqrt

* added test to check fails when ls into prohibited dir

* fix lint

* math sqrt with tests and doc

* trigger wasm build

* Update filesystem_shell.rs

* converted math commands to outputstream and new method for arg evaluation

* fmt

* clippy

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
Luccas Mateus 2021-04-14 15:18:37 -03:00 committed by GitHub
parent a148c640b2
commit 004230d02d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 78 additions and 93 deletions

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
"Returns absolute values of a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => {
UntaggedValue::int(val.magnitude().clone()).into()
@ -31,7 +31,7 @@ impl WholeStreamCommand for SubCommand {
}
other => abs_default(other),
});
Ok(ActionStream::from_input(mapped))
Ok(mapped.to_output_stream())
}
fn examples(&self) -> Vec<Example> {

View File

@ -27,7 +27,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the average of a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, average)
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the ceil function to a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input;
run_with_numerical_functions_on_stream(input, ceil_big_int, ceil_big_decimal, ceil_default)

View File

@ -1,7 +1,7 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
use nu_protocol::{Signature, UntaggedValue};
pub struct Command;
@ -18,10 +18,10 @@ impl WholeStreamCommand for Command {
"Use mathematical functions as aggregate functions on a list of numbers or tables."
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
Ok(ActionStream::one(Ok(ReturnSuccess::Value(
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(OutputStream::one(
UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()),
))))
))
}
}

View File

@ -1,16 +1,11 @@
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
pub struct SubCommand;
#[derive(Deserialize)]
pub struct SubCommandArgs {
expression: Option<Tagged<String>>,
}
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"math eval"
@ -28,7 +23,7 @@ impl WholeStreamCommand for SubCommand {
)
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
eval(args)
}
@ -45,13 +40,15 @@ impl WholeStreamCommand for SubCommand {
}
}
pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
let name = args.call_info.name_tag.span;
let (SubCommandArgs { expression }, input) = args.process()?;
pub fn eval(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once()?;
let expression: Option<Result<Tagged<String>, ShellError>> = args.opt(0);
let name = args.call_info.name_tag.clone();
let input = args.input;
if let Some(string) = expression {
if let Some(Ok(string)) = expression {
match parse(&string, &string.tag) {
Ok(value) => Ok(ActionStream::one(ReturnSuccess::value(value))),
Ok(value) => Ok(OutputStream::one(value)),
Err(err) => Err(ShellError::labeled_error(
"Math evaluation error",
err,
@ -59,12 +56,12 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
)),
}
} else {
Ok(input
let mapped: Result<Vec<_>, _> = input
.map(move |x| {
if let Some(Tagged {
if let Some(Ok(Tagged {
tag,
item: expression,
}) = &expression
})) = &expression
{
UntaggedValue::string(expression).into_value(tag)
} else {
@ -74,7 +71,7 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
.map(move |input| {
if let Ok(string) = input.as_string() {
match parse(&string, &input.tag) {
Ok(value) => ReturnSuccess::value(value),
Ok(value) => Ok(value),
Err(err) => Err(ShellError::labeled_error(
"Math evaluation error",
err,
@ -85,11 +82,15 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
Err(ShellError::labeled_error(
"Expected a string from pipeline",
"requires string input",
name,
name.clone(),
))
}
})
.to_action_stream())
.collect();
match mapped {
Ok(values) => Ok(OutputStream::from(values)),
Err(e) => Err(e),
}
}
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the floor function to a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input;
run_with_numerical_functions_on_stream(

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the maximum within a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, maximum)
}

View File

@ -24,7 +24,7 @@ impl WholeStreamCommand for SubCommand {
"Gets the median of a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, median)
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the minimum within a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, minimum)
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Gets the most frequent element(s) from a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, mode)
}

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the product of a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, product)
}

View File

@ -6,11 +6,6 @@ use nu_source::Tagged;
pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
precision: Option<Tagged<i64>>,
}
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"math round"
@ -29,7 +24,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the round function to a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
operate(args)
}
@ -57,16 +52,23 @@ impl WholeStreamCommand for SubCommand {
}
}
fn operate(args: CommandArgs) -> Result<ActionStream, ShellError> {
let (Arguments { precision }, input) = args.process()?;
let precision = precision.map(|p| p.item).unwrap_or(0);
fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let args = args.evaluate_once()?;
let precision: Option<Result<Tagged<i16>, ShellError>> = args.get_flag("precision");
let input = args.input;
let precision = if let Some(precision) = precision {
precision?.item
} else {
0
};
let mapped = input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => round_big_int(val),
UntaggedValue::Primitive(Primitive::Decimal(val)) => round_big_decimal(val, precision),
UntaggedValue::Primitive(Primitive::Decimal(val)) => {
round_big_decimal(val, precision.into())
}
other => round_default(other),
});
Ok(ActionStream::from_input(mapped))
Ok(mapped.to_output_stream())
}
fn round_big_int(val: BigInt) -> Value {

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the square root function to a list of numbers"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(operate(args))
}
@ -34,13 +34,13 @@ impl WholeStreamCommand for SubCommand {
}
}
fn operate(args: CommandArgs) -> ActionStream {
fn operate(args: CommandArgs) -> OutputStream {
let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => sqrt_big_decimal(BigDecimal::from(val)),
UntaggedValue::Primitive(Primitive::Decimal(val)) => sqrt_big_decimal(val),
other => sqrt_default(other),
});
ActionStream::from_input(mapped)
mapped.to_output_stream()
}
fn sqrt_big_decimal(val: BigDecimal) -> Value {

View File

@ -2,17 +2,11 @@ use super::variance::compute_variance as variance;
use crate::prelude::*;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
use nu_source::Tagged;
use nu_protocol::{Dictionary, Primitive, Signature, UntaggedValue, Value};
use std::str::FromStr;
pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
sample: Tagged<bool>,
}
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"math stddev"
@ -30,13 +24,14 @@ impl WholeStreamCommand for SubCommand {
"Finds the stddev of a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut args = raw_args.evaluate_once()?;
let sample: bool = args.has_flag("sample");
let values: Vec<Value> = args.input.drain_vec();
let name = args.call_info.name_tag.clone();
let (Arguments { sample }, mut input) = args.process()?;
let values: Vec<Value> = input.drain_vec();
let n = if let Tagged { item: true, .. } = sample {
let n = if sample {
values.len() - 1
} else {
values.len()
@ -81,13 +76,11 @@ impl WholeStreamCommand for SubCommand {
}?;
if res.value.is_table() {
Ok(ActionStream::from(
res.table_entries()
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
Ok(OutputStream::from(
res.table_entries().cloned().collect::<Vec<_>>(),
))
} else {
Ok(ActionStream::one(ReturnSuccess::value(res)))
Ok(OutputStream::one(res))
}
}

View File

@ -21,7 +21,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the sum of a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, summation)
}

View File

@ -1,6 +1,6 @@
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, UntaggedValue, Value};
use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value};
use indexmap::map::IndexMap;
@ -9,7 +9,7 @@ pub type MathFunction = fn(values: &[Value], tag: &Tag) -> Result<Value, ShellEr
pub fn run_with_function(
args: impl Into<RunnableContext>,
mf: MathFunction,
) -> Result<ActionStream, ShellError> {
) -> Result<OutputStream, ShellError> {
let RunnableContext {
mut input,
call_info,
@ -23,13 +23,11 @@ pub fn run_with_function(
match res {
Ok(v) => {
if v.value.is_table() {
Ok(ActionStream::from(
v.table_entries()
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
Ok(OutputStream::from(
v.table_entries().cloned().collect::<Vec<_>>(),
))
} else {
Ok(ActionStream::one(ReturnSuccess::value(v)))
Ok(OutputStream::one(v))
}
}
Err(e) => Err(e),
@ -47,13 +45,13 @@ pub fn run_with_numerical_functions_on_stream(
int_function: IntFunction,
decimal_function: DecimalFunction,
default_function: DefaultFunction,
) -> Result<ActionStream, ShellError> {
) -> Result<OutputStream, ShellError> {
let mapped = input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => int_function(val),
UntaggedValue::Primitive(Primitive::Decimal(val)) => decimal_function(val),
other => default_function(other),
});
Ok(ActionStream::from_input(mapped))
Ok(mapped.to_output_stream())
}
pub fn calculate(values: &[Value], name: &Tag, mf: MathFunction) -> Result<Value, ShellError> {

View File

@ -3,18 +3,10 @@ use bigdecimal::FromPrimitive;
use nu_data::value::compute_values;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
use nu_protocol::{
hir::Operator, Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value,
};
use nu_source::Tagged;
use nu_protocol::{hir::Operator, Dictionary, Primitive, Signature, UntaggedValue, Value};
pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
sample: Tagged<bool>,
}
impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str {
"math variance"
@ -28,13 +20,14 @@ impl WholeStreamCommand for SubCommand {
"Finds the variance of a list of numbers or tables"
}
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut args = raw_args.evaluate_once()?;
let sample: bool = args.has_flag("sample");
let values: Vec<Value> = args.input.drain_vec();
let name = args.call_info.name_tag.clone();
let (Arguments { sample }, mut input) = args.process()?;
let values: Vec<Value> = input.drain_vec();
let n = if let Tagged { item: true, .. } = sample {
let n = if sample {
values.len() - 1
} else {
values.len()
@ -79,13 +72,11 @@ impl WholeStreamCommand for SubCommand {
}?;
if res.value.is_table() {
Ok(ActionStream::from(
res.table_entries()
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
Ok(OutputStream::from(
res.table_entries().cloned().collect::<Vec<_>>(),
))
} else {
Ok(ActionStream::one(ReturnSuccess::value(res)))
Ok(OutputStream::one(res))
}
}