nushell/crates/nu-command/src/math/reducers.rs
Stefan Holderbach 6a7a60429f
Remove unnecessary #[allow(...)] annotations (#6870)
* Remove unnecessary `#[allow]` annots

Reduce the number of lint exceptions that are not necessary with the
current state of the code (or more recent toolchain)

* Remove dead code from `FileStructure` in nu-command

* Replace `allow(unused)` with relevant feature switch

* Deal with `needless_collect` with annotations

* Change hack for needless_collect in `from json`

This change obviates the need for `allow(needless_collect)`
Removes a pessimistic allocation for empty strings, but increases
allocation size to `Value`

Probably not really worth it.

* Revert "Deal with `needless_collect` with annotations"

This reverts commit 05aca98445.

The previous state seems to better from a performance perspective as a
`Vec<String>` is lighter weight than `Vec<Value>`
2022-10-24 20:12:16 +02:00

143 lines
4.2 KiB
Rust

use nu_protocol::{ShellError, Span, Value};
use std::cmp::Ordering;
pub enum Reduce {
Summation,
Product,
Minimum,
Maximum,
}
pub type ReducerFunction =
Box<dyn Fn(Value, Vec<Value>, Span) -> Result<Value, ShellError> + Send + Sync + 'static>;
pub fn reducer_for(command: Reduce) -> ReducerFunction {
match command {
Reduce::Summation => Box::new(|_, values, head| sum(values, head)),
Reduce::Product => Box::new(|_, values, head| product(values, head)),
Reduce::Minimum => Box::new(|_, values, head| min(values, head)),
Reduce::Maximum => Box::new(|_, values, head| max(values, head)),
}
}
pub fn max(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let mut biggest = data
.first()
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), head))?
.clone();
for value in &data {
if let Some(result) = value.partial_cmp(&biggest) {
if result == Ordering::Greater {
biggest = value.clone();
}
} else {
return Err(ShellError::OperatorMismatch {
op_span: head,
lhs_ty: biggest.get_type(),
lhs_span: biggest.span()?,
rhs_ty: value.get_type(),
rhs_span: value.span()?,
});
}
}
Ok(biggest)
}
pub fn min(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let mut smallest = data
.first()
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), head))?
.clone();
for value in &data {
if let Some(result) = value.partial_cmp(&smallest) {
if result == Ordering::Less {
smallest = value.clone();
}
} else {
return Err(ShellError::OperatorMismatch {
op_span: head,
lhs_ty: smallest.get_type(),
lhs_span: smallest.span()?,
rhs_ty: value.get_type(),
rhs_span: value.span()?,
});
}
}
Ok(smallest)
}
pub fn sum(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let initial_value = data.get(0);
let mut acc = match initial_value {
Some(Value::Filesize { span, .. }) => Ok(Value::Filesize {
val: 0,
span: *span,
}),
Some(Value::Duration { span, .. }) => Ok(Value::Duration {
val: 0,
span: *span,
}),
Some(Value::Int { span, .. }) | Some(Value::Float { span, .. }) => Ok(Value::Int {
val: 0,
span: *span,
}),
None => Err(ShellError::UnsupportedInput(
"Empty input".to_string(),
head,
)),
_ => Ok(Value::nothing(head)),
}?;
for value in &data {
match value {
Value::Int { .. }
| Value::Float { .. }
| Value::Filesize { .. }
| Value::Duration { .. } => {
acc = acc.add(head, value, head)?;
}
other => {
return Err(ShellError::UnsupportedInput(
"Attempted to compute the sum of a value that cannot be summed".to_string(),
other.span().unwrap_or(head),
));
}
}
}
Ok(acc)
}
pub fn product(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
let initial_value = data.get(0);
let mut acc = match initial_value {
Some(Value::Int { span, .. }) | Some(Value::Float { span, .. }) => Ok(Value::Int {
val: 1,
span: *span,
}),
None => Err(ShellError::UnsupportedInput(
"Empty input".to_string(),
head,
)),
_ => Ok(Value::nothing(head)),
}?;
for value in &data {
match value {
Value::Int { .. } | Value::Float { .. } => {
acc = acc.mul(head, value, head)?;
}
other => {
return Err(ShellError::UnsupportedInput(
"Attempted to compute the product of a value that cannot be multiplied"
.to_string(),
other.span().unwrap_or(head),
));
}
}
}
Ok(acc)
}