mirror of
https://github.com/nushell/nushell
synced 2025-01-09 19:59:02 +00:00
6a7a60429f
* 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>`
143 lines
4.2 KiB
Rust
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)
|
|
}
|