forked from extern/nushell
Box ShellError
in Value::Error
(#8375)
# Description Our `ShellError` at the moment has a `std::mem::size_of<ShellError>` of 136 bytes (on AMD64). As a result `Value` directly storing the struct also required 136 bytes (thanks to alignment requirements). This change stores the `Value::Error` `ShellError` on the heap. Pro: - Value now needs just 80 bytes - Should be 1 cacheline less (still at least 2 cachelines) Con: - More small heap allocations when dealing with `Value::Error` - More heap fragmentation - Potential for additional required memcopies # Further code changes Includes a small refactor of `try` due to a type mismatch in its large match. # User-Facing Changes None for regular users. Plugin authors may have to update their matches on `Value` if they use `nu-protocol` Needs benchmarking to see if there is a benefit in real world workloads. **Update** small improvements in runtime for workloads with high volume of values. Significant reduction in maximum resident set size, when many values are held in memory. # Tests + Formatting
This commit is contained in:
parent
c26d91fb61
commit
a52386e837
@ -145,7 +145,7 @@ pub(crate) fn print_table_or_error(
|
||||
|
||||
if let PipelineData::Value(Value::Error { error }, ..) = &pipeline_data {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
report_error(&working_set, error);
|
||||
report_error(&working_set, &**error);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ fn print_or_exit(pipeline_data: PipelineData, engine_state: &mut EngineState, co
|
||||
if let Value::Error { error } = item {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
|
||||
report_error(&working_set, &error);
|
||||
report_error(&working_set, &*error);
|
||||
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
@ -53,7 +53,9 @@ impl Command for NuHighlight {
|
||||
span: head,
|
||||
}
|
||||
}
|
||||
Err(err) => Value::Error { error: err },
|
||||
Err(err) => Value::Error {
|
||||
error: Box::new(err),
|
||||
},
|
||||
},
|
||||
ctrlc,
|
||||
)
|
||||
|
@ -1124,7 +1124,7 @@ fn run_hook_block(
|
||||
eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)?;
|
||||
|
||||
if let PipelineData::Value(Value::Error { error }, _) = pipeline_data {
|
||||
return Err(error);
|
||||
return Err(*error);
|
||||
}
|
||||
|
||||
// If all went fine, preserve the environment of the called block
|
||||
|
@ -57,66 +57,29 @@ impl Command for Try {
|
||||
let result = eval_block(engine_state, stack, try_block, input, false, false);
|
||||
|
||||
match result {
|
||||
Err(error) | Ok(PipelineData::Value(Value::Error { error }, ..)) => {
|
||||
if let nu_protocol::ShellError::Break(_) = error {
|
||||
return Err(error);
|
||||
} else if let nu_protocol::ShellError::Continue(_) = error {
|
||||
return Err(error);
|
||||
} else if let nu_protocol::ShellError::Return(_, _) = error {
|
||||
return Err(error);
|
||||
}
|
||||
if let Some(catch_block) = catch_block {
|
||||
let catch_block = engine_state.get_block(catch_block.block_id);
|
||||
let err_value = Value::Error { error };
|
||||
// Put the error value in the positional closure var
|
||||
if let Some(var) = catch_block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(*var_id, err_value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
eval_block(
|
||||
engine_state,
|
||||
stack,
|
||||
catch_block,
|
||||
// Make the error accessible with $in, too
|
||||
err_value.into_pipeline_data(),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
Ok(PipelineData::empty())
|
||||
}
|
||||
Err(error) => {
|
||||
let error = intercept_block_control(error)?;
|
||||
let err_value = Value::Error {
|
||||
error: Box::new(error),
|
||||
};
|
||||
handle_catch(err_value, catch_block, engine_state, stack)
|
||||
}
|
||||
Ok(PipelineData::Value(Value::Error { error }, ..)) => {
|
||||
let error = intercept_block_control(*error)?;
|
||||
let err_value = Value::Error {
|
||||
error: Box::new(error),
|
||||
};
|
||||
handle_catch(err_value, catch_block, engine_state, stack)
|
||||
}
|
||||
// external command may fail to run
|
||||
Ok(pipeline) => {
|
||||
let (pipeline, external_failed) = pipeline.is_external_failed();
|
||||
if external_failed {
|
||||
if let Some(catch_block) = catch_block {
|
||||
let catch_block = engine_state.get_block(catch_block.block_id);
|
||||
|
||||
if let Some(var) = catch_block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
// Because external command errors aren't "real" errors,
|
||||
// (unless do -c is in effect)
|
||||
// they can't be passed in as Nushell values.
|
||||
let err_value = Value::nothing(call.head);
|
||||
stack.add_var(*var_id, err_value);
|
||||
}
|
||||
}
|
||||
|
||||
eval_block(
|
||||
engine_state,
|
||||
stack,
|
||||
catch_block,
|
||||
// The same null as in the above block is set as the $in value.
|
||||
Value::nothing(call.head).into_pipeline_data(),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
Ok(PipelineData::empty())
|
||||
}
|
||||
// Because external command errors aren't "real" errors,
|
||||
// (unless do -c is in effect)
|
||||
// they can't be passed in as Nushell values.
|
||||
let err_value = Value::nothing(call.head);
|
||||
handle_catch(err_value, catch_block, engine_state, stack)
|
||||
} else {
|
||||
Ok(pipeline)
|
||||
}
|
||||
@ -140,6 +103,48 @@ impl Command for Try {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_catch(
|
||||
err_value: Value,
|
||||
catch_block: Option<Closure>,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
if let Some(catch_block) = catch_block {
|
||||
let catch_block = engine_state.get_block(catch_block.block_id);
|
||||
// Put the error value in the positional closure var
|
||||
if let Some(var) = catch_block.signature.get_positional(0) {
|
||||
if let Some(var_id) = &var.var_id {
|
||||
stack.add_var(*var_id, err_value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
eval_block(
|
||||
engine_state,
|
||||
stack,
|
||||
catch_block,
|
||||
// Make the error accessible with $in, too
|
||||
err_value.into_pipeline_data(),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
Ok(PipelineData::empty())
|
||||
}
|
||||
}
|
||||
|
||||
/// The flow control commands `break`/`continue`/`return` emit their own [`ShellError`] variants
|
||||
/// We need to ignore those in `try` and bubble them through
|
||||
///
|
||||
/// `Err` when flow control to bubble up with `?`
|
||||
fn intercept_block_control(error: ShellError) -> Result<ShellError, ShellError> {
|
||||
match error {
|
||||
nu_protocol::ShellError::Break(_) => Err(error),
|
||||
nu_protocol::ShellError::Continue(_) => Err(error),
|
||||
nu_protocol::ShellError::Return(_, _) => Err(error),
|
||||
_ => Ok(error),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -81,12 +81,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -150,12 +150,12 @@ fn operate(value: Value, head: Span, signed: bool, number_size: NumberBytes) ->
|
||||
// Propagate errors inside the value
|
||||
Value::Error { .. } => other,
|
||||
_ => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -81,12 +81,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ where
|
||||
match rotate_result {
|
||||
Ok(val) => Value::Int { val, span },
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Rotate left result beyond the range of 64 bit signed number".to_string(),
|
||||
format!(
|
||||
"{val} of the specified number of bytes rotate left {bits} bits exceed limit"
|
||||
@ -111,7 +111,7 @@ where
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -137,12 +137,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ where
|
||||
match rotate_result {
|
||||
Ok(val) => Value::Int { val, span },
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Rotate right result beyond the range of 64 bit signed number".to_string(),
|
||||
format!(
|
||||
"{val} of the specified number of bytes rotate right {bits} bits exceed limit"
|
||||
@ -115,7 +115,7 @@ where
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -141,12 +141,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ where
|
||||
match shift_result {
|
||||
Ok(val) => Value::Int { val, span },
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Shift left result beyond the range of 64 bit signed number".to_string(),
|
||||
format!(
|
||||
"{val} of the specified number of bytes shift left {bits} bits exceed limit"
|
||||
@ -123,18 +123,18 @@ where
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
None => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Shift left failed".to_string(),
|
||||
format!("{val} shift left {bits} bits failed, you may shift too many bits"),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -160,12 +160,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ where
|
||||
match shift_result {
|
||||
Ok(val) => Value::Int { val, span },
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Shift right result beyond the range of 64 bit signed number".to_string(),
|
||||
format!(
|
||||
"{val} of the specified number of bytes shift right {bits} bits exceed limit"
|
||||
@ -113,18 +113,18 @@ where
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
None => Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
"Shift right failed".to_string(),
|
||||
format!("{val} shift right {bits} bits failed, you may shift too many bits"),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -150,12 +150,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -80,12 +80,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -125,12 +125,12 @@ fn add(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::String { val, .. } => val,
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Only string or list<int> ranges are supported".into(),
|
||||
@ -56,7 +56,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::String { val, .. } => val,
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Only string or list<int> ranges are supported".into(),
|
||||
@ -84,7 +84,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
|
||||
}
|
||||
}
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"could not perform subbytes".to_string(),
|
||||
@ -249,12 +249,12 @@ fn at(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -277,10 +277,10 @@ fn at_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
|
||||
match start.cmp(&end) {
|
||||
Ordering::Equal => Value::Binary { val: vec![], span },
|
||||
Ordering::Greater => Value::Error {
|
||||
error: ShellError::TypeMismatch {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
err_message: "End must be greater than or equal to Start".to_string(),
|
||||
span: arg.arg_span,
|
||||
},
|
||||
}),
|
||||
},
|
||||
Ordering::Less => Value::Binary {
|
||||
val: {
|
||||
|
@ -53,7 +53,7 @@ impl Command for BytesBuild {
|
||||
match val {
|
||||
Value::Binary { mut val, .. } => output.append(&mut val),
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::TypeMismatch {
|
||||
err_message: "only binary data arguments are supported".to_string(),
|
||||
|
@ -55,7 +55,7 @@ impl Command for BytesCollect {
|
||||
}
|
||||
}
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
|
@ -93,12 +93,12 @@ fn ends_with(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -135,12 +135,12 @@ fn index_of(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -74,12 +74,12 @@ fn length(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -142,12 +142,12 @@ fn remove(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -133,12 +133,12 @@ fn replace(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -84,12 +84,12 @@ fn reverse(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -80,12 +80,12 @@ impl Command for BytesStartsWith {
|
||||
// Unsupported data
|
||||
Ok(other) => {
|
||||
return Ok(Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string and binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
}
|
||||
.into_pipeline_data());
|
||||
}
|
||||
@ -149,12 +149,12 @@ fn starts_with(val: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => val.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ impl HashableValue {
|
||||
Value::Binary { val, span } => Ok(HashableValue::Binary { val, span }),
|
||||
|
||||
// Explicitly propagate errors instead of dropping them.
|
||||
Value::Error { error } => Err(error),
|
||||
Value::Error { error } => Err(*error),
|
||||
_ => Err(ShellError::UnsupportedInput(
|
||||
"input value is not hashable".into(),
|
||||
format!("input type: {:?}", value.get_type()),
|
||||
@ -236,7 +236,7 @@ mod test {
|
||||
},
|
||||
Value::Nothing { span },
|
||||
Value::Error {
|
||||
error: ShellError::DidYouMean("what?".to_string(), span),
|
||||
error: Box::new(ShellError::DidYouMean("what?".to_string(), span)),
|
||||
},
|
||||
Value::CellPath {
|
||||
val: CellPath {
|
||||
|
@ -160,7 +160,7 @@ fn run_histogram(
|
||||
for v in values {
|
||||
match v {
|
||||
// Propagate existing errors.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
_ => {
|
||||
let t = v.get_type();
|
||||
let span = v.expect_span();
|
||||
@ -198,7 +198,7 @@ fn run_histogram(
|
||||
}
|
||||
}
|
||||
// Propagate existing errors.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
@ -193,12 +193,12 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "int, filesize, float, string".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -87,12 +87,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer or filesize".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -188,13 +188,13 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer, float, filesize, string, date, duration, binary or bool"
|
||||
.into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -161,17 +161,19 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
},
|
||||
Value::String { val, .. } => match string_to_boolean(val, span) {
|
||||
Ok(val) => Value::Bool { val, span },
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
},
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "bool, integer, float or string".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -209,12 +209,12 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Value::Error { .. } => return input.clone(),
|
||||
other => {
|
||||
return Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string and integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -245,21 +245,21 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Zone::East(i) => match FixedOffset::east_opt((*i as i32) * HOUR) {
|
||||
Some(eastoffset) => match_datetime!(eastoffset.timestamp_nanos(ts)),
|
||||
None => Value::Error {
|
||||
error: ShellError::DatetimeParseError(input.debug_value(), *span),
|
||||
error: Box::new(ShellError::DatetimeParseError(input.debug_value(), *span)),
|
||||
},
|
||||
},
|
||||
Zone::West(i) => match FixedOffset::west_opt((*i as i32) * HOUR) {
|
||||
Some(westoffset) => match_datetime!(westoffset.timestamp_nanos(ts)),
|
||||
None => Value::Error {
|
||||
error: ShellError::DatetimeParseError(input.debug_value(), *span),
|
||||
error: Box::new(ShellError::DatetimeParseError(input.debug_value(), *span)),
|
||||
},
|
||||
},
|
||||
Zone::Error => Value::Error {
|
||||
// This is an argument error, not an input error
|
||||
error: ShellError::TypeMismatch {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
err_message: "Invalid timezone or offset".to_string(),
|
||||
span: *span,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -273,7 +273,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Ok(d) => Value::Date { val: d, span: head },
|
||||
Err(reason) => {
|
||||
Value::Error {
|
||||
error: ShellError::CantConvert { to_type: format!("could not parse as datetime using format '{}'", dt.0), from_type: reason.to_string(), span: head, help: Some("you can use `into datetime` without a format string to enable flexible parsing".to_string()) },
|
||||
error: Box::new(ShellError::CantConvert { to_type: format!("could not parse as datetime using format '{}'", dt.0), from_type: reason.to_string(), span: head, help: Some("you can use `into datetime` without a format string to enable flexible parsing".to_string()) }),
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -292,12 +292,12 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -374,7 +374,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn takes_timestamp_offset_as_int() {
|
||||
let date_int = Value::test_int(1614434140_000000000);
|
||||
let date_int = Value::test_int(1_614_434_140_000_000_000);
|
||||
let timezone_option = Some(Spanned {
|
||||
item: Zone::East(8),
|
||||
span: Span::test_data(),
|
||||
|
@ -88,12 +88,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
|
||||
match other.parse::<f64>() {
|
||||
Ok(x) => Value::float(x, head),
|
||||
Err(reason) => Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "float".to_string(),
|
||||
from_type: reason.to_string(),
|
||||
span: *span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -108,12 +108,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string, integer or bool".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,9 @@ fn into_duration(
|
||||
Box::new(move |old| action(old, &d, float_precision, head)),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,7 +432,7 @@ fn action(
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
} else {
|
||||
input.clone()
|
||||
@ -464,34 +466,36 @@ fn action(
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "string".into(),
|
||||
from_type: "duration".into(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match string_to_duration(val, span, *value_span) {
|
||||
Ok(val) => Value::Duration { val, span },
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string or duration".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -110,19 +110,21 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
|
||||
val,
|
||||
span: value_span,
|
||||
},
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
},
|
||||
Value::Nothing { .. } => Value::Filesize {
|
||||
val: 0,
|
||||
span: value_span,
|
||||
},
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string and integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: value_span,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
@ -189,12 +189,12 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
Ok(v) => v,
|
||||
_ => {
|
||||
return Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "float".to_string(),
|
||||
from_type: "integer".to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,7 +206,9 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
if radix == 10 {
|
||||
match int_from_string(val, span) {
|
||||
Ok(val) => Value::Int { val, span },
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
convert_int(input, span, radix)
|
||||
@ -232,10 +234,10 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
.unwrap()
|
||||
{
|
||||
Value::Error {
|
||||
error: ShellError::IncorrectValue {
|
||||
error: Box::new(ShellError::IncorrectValue {
|
||||
msg: "DateTime out of range for timestamp: 1677-09-21T00:12:43Z to 2262-04-11T23:47:16".to_string(),
|
||||
span
|
||||
},
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
Value::Int {
|
||||
@ -269,13 +271,13 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "integer, float, filesize, date, string, binary, duration or bool"
|
||||
.into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -292,7 +294,7 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
|
||||
{
|
||||
match int_from_string(val, head) {
|
||||
Ok(x) => return Value::int(x, head),
|
||||
Err(e) => return Value::Error { error: e },
|
||||
Err(e) => return Value::Error { error: Box::new(e) },
|
||||
}
|
||||
} else if val.starts_with("00") {
|
||||
// It's a padded string
|
||||
@ -300,12 +302,12 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
|
||||
Ok(n) => return Value::int(n, head),
|
||||
Err(e) => {
|
||||
return Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "int".to_string(),
|
||||
span: head,
|
||||
help: Some(e.to_string()),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,24 +318,24 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
|
||||
Value::Error { .. } => return input.clone(),
|
||||
other => {
|
||||
return Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string and integer".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
match i64::from_str_radix(i.trim(), radix) {
|
||||
Ok(n) => Value::int(n, head),
|
||||
Err(_reason) => Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "int".to_string(),
|
||||
span: head,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -483,9 +485,9 @@ mod test {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case("2262-04-11T23:47:16+00:00", 0x7fffffff_ffffffff)]
|
||||
#[case("2262-04-11T23:47:16+00:00", 0x7fff_ffff_ffff_ffff)]
|
||||
#[case("1970-01-01T00:00:00+00:00", 0)]
|
||||
#[case("1677-09-21T00:12:44+00:00", -0x7fffffff_ffffffff)]
|
||||
#[case("1677-09-21T00:12:44+00:00", -0x7fff_ffff_ffff_ffff)]
|
||||
fn datetime_to_int_values_that_work(
|
||||
#[case] dt_in: DateTime<FixedOffset>,
|
||||
#[case] int_expected: i64,
|
||||
@ -522,14 +524,15 @@ mod test {
|
||||
},
|
||||
Span::test_data(),
|
||||
);
|
||||
if let Value::Error {
|
||||
error: ShellError::IncorrectValue { msg: e, .. },
|
||||
} = actual
|
||||
{
|
||||
assert!(
|
||||
e.contains(err_expected),
|
||||
"{e:?} doesn't contain {err_expected}"
|
||||
);
|
||||
if let Value::Error { error } = actual {
|
||||
if let ShellError::IncorrectValue { msg: e, .. } = *error {
|
||||
assert!(
|
||||
e.contains(err_expected),
|
||||
"{e:?} doesn't contain {err_expected}"
|
||||
);
|
||||
} else {
|
||||
panic!("Unexpected error variant {error:?}")
|
||||
}
|
||||
} else {
|
||||
panic!("Unexpected actual value {actual:?}")
|
||||
}
|
||||
|
@ -185,12 +185,12 @@ fn into_record(
|
||||
Value::Record { cols, vals, span } => Value::Record { cols, vals, span },
|
||||
Value::Error { .. } => input,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: call.head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
Ok(res.into_pipeline_data())
|
||||
|
@ -247,28 +247,28 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
|
||||
span: _,
|
||||
} => Value::Error {
|
||||
// Watch out for CantConvert's argument order
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "string".into(),
|
||||
from_type: "record".into(),
|
||||
span,
|
||||
help: Some("try using the `to nuon` command".into()),
|
||||
},
|
||||
}),
|
||||
},
|
||||
Value::Binary { .. } => Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "string".into(),
|
||||
from_type: "binary".into(),
|
||||
span,
|
||||
help: Some("try using the `decode` command".into()),
|
||||
},
|
||||
}),
|
||||
},
|
||||
x => Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: String::from("string"),
|
||||
from_type: x.get_type().to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ fn action(
|
||||
Ok(Value::Nothing { span: *span })
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
other => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
|
@ -463,7 +463,7 @@ pub fn convert_sqlite_value_to_nu_value(value: ValueRef, span: Span) -> Value {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
return Value::Error {
|
||||
error: ShellError::NonUtf8(span),
|
||||
error: Box::new(ShellError::NonUtf8(span)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -461,13 +461,13 @@ pub fn create_column(
|
||||
Some(val) => val,
|
||||
None => {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"The given local datetime representation is invalid."
|
||||
.to_string(),
|
||||
format!("timestamp is {a:?}"),
|
||||
span,
|
||||
Span::unknown(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -476,13 +476,13 @@ pub fn create_column(
|
||||
Some(val) => val,
|
||||
None => {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"The given local datetime representation is invalid."
|
||||
.to_string(),
|
||||
format!("timestamp is {a:?}"),
|
||||
span,
|
||||
Span::unknown(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -526,13 +526,13 @@ pub fn create_column(
|
||||
Some(val) => val,
|
||||
None => {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"The given local datetime representation is invalid."
|
||||
.to_string(),
|
||||
format!("timestamp is {a:?}"),
|
||||
span,
|
||||
Span::unknown(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -541,13 +541,13 @@ pub fn create_column(
|
||||
Some(val) => val,
|
||||
None => {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"The given local datetime representation is invalid."
|
||||
.to_string(),
|
||||
format!("timestamp is {a:?}"),
|
||||
span,
|
||||
Span::unknown(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -132,10 +132,10 @@ where
|
||||
span,
|
||||
},
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::TypeMismatch {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
err_message: "invalid format".to_string(),
|
||||
span,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,10 @@ fn format_helper(value: Value, formatter: &str, formatter_span: Span, head_span:
|
||||
}
|
||||
}
|
||||
_ => Value::Error {
|
||||
error: ShellError::DatetimeParseError(value.debug_value(), head_span),
|
||||
error: Box::new(ShellError::DatetimeParseError(
|
||||
value.debug_value(),
|
||||
head_span,
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -177,7 +180,7 @@ fn format_helper_rfc2822(value: Value, span: Span) -> Value {
|
||||
}
|
||||
}
|
||||
_ => Value::Error {
|
||||
error: ShellError::DatetimeParseError(value.debug_value(), span),
|
||||
error: Box::new(ShellError::DatetimeParseError(value.debug_value(), span)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ fn helper(value: Value, head: Span) -> Value {
|
||||
span: head,
|
||||
},
|
||||
_ => Value::Error {
|
||||
error: ShellError::DatetimeParseError(value.debug_value(), head),
|
||||
error: Box::new(ShellError::DatetimeParseError(value.debug_value(), head)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ fn helper(val: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head),
|
||||
_ => Value::Error {
|
||||
error: DatetimeParseError(val.debug_value(), head),
|
||||
error: Box::new(DatetimeParseError(val.debug_value(), head)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ fn helper(val: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head),
|
||||
_ => Value::Error {
|
||||
error: DatetimeParseError(val.debug_value(), head),
|
||||
error: Box::new(DatetimeParseError(val.debug_value(), head)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ fn helper(value: Value, head: Span, timezone: &Spanned<String>) -> Value {
|
||||
_to_timezone(dt.with_timezone(dt.offset()), timezone, head)
|
||||
}
|
||||
_ => Value::Error {
|
||||
error: ShellError::DatetimeParseError(value.debug_value(), head),
|
||||
error: Box::new(ShellError::DatetimeParseError(value.debug_value(), head)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -137,10 +137,10 @@ fn _to_timezone(dt: DateTime<FixedOffset>, timezone: &Spanned<String>, span: Spa
|
||||
match datetime_in_timezone(&dt, timezone.item.as_str()) {
|
||||
Ok(dt) => Value::Date { val: dt, span },
|
||||
Err(_) => Value::Error {
|
||||
error: ShellError::TypeMismatch {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
err_message: String::from("invalid time zone"),
|
||||
span: timezone.span,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ pub(crate) fn parse_date_from_string(
|
||||
LocalResult::Single(d) => Ok(d),
|
||||
LocalResult::Ambiguous(d, _) => Ok(d),
|
||||
LocalResult::None => Err(Value::Error {
|
||||
error: ShellError::DatetimeParseError(input.to_string(), span),
|
||||
error: Box::new(ShellError::DatetimeParseError(input.to_string(), span)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
Err(_) => Err(Value::Error {
|
||||
error: ShellError::DatetimeParseError(input.to_string(), span),
|
||||
error: Box::new(ShellError::DatetimeParseError(input.to_string(), span)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,9 @@ fn get_expression_as_value(
|
||||
) -> Value {
|
||||
match eval_expression(engine_state, stack, inner_expr) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,13 +379,13 @@ fn interactive_copy(
|
||||
);
|
||||
if let Err(e) = interaction {
|
||||
Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
e.to_string(),
|
||||
e.to_string(),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
} else if !confirmed {
|
||||
let msg = format!("{:} not copied to {:}", src.display(), dst.display());
|
||||
@ -518,13 +518,13 @@ fn copy_symlink(
|
||||
Ok(p) => p,
|
||||
Err(err) => {
|
||||
return Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
err.to_string(),
|
||||
err.to_string(),
|
||||
Some(span),
|
||||
None,
|
||||
vec![],
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -551,7 +551,13 @@ fn copy_symlink(
|
||||
Value::String { val: msg, span }
|
||||
}
|
||||
Err(e) => Value::Error {
|
||||
error: ShellError::GenericError(e.to_string(), e.to_string(), Some(span), None, vec![]),
|
||||
error: Box::new(ShellError::GenericError(
|
||||
e.to_string(),
|
||||
e.to_string(),
|
||||
Some(span),
|
||||
None,
|
||||
vec![],
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -593,5 +599,7 @@ fn convert_io_error(error: std::io::Error, src: PathBuf, dst: PathBuf, span: Spa
|
||||
_ => ShellError::IOErrorSpanned(message_src, span),
|
||||
};
|
||||
|
||||
Value::Error { error: shell_error }
|
||||
Value::Error {
|
||||
error: Box::new(shell_error),
|
||||
}
|
||||
}
|
||||
|
@ -255,10 +255,14 @@ impl Command for Ls {
|
||||
);
|
||||
match entry {
|
||||
Ok(value) => Some(value),
|
||||
Err(err) => Some(Value::Error { error: err }),
|
||||
Err(err) => Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
}),
|
||||
}
|
||||
}
|
||||
Err(err) => Some(Value::Error { error: err }),
|
||||
Err(err) => Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
}),
|
||||
}
|
||||
}
|
||||
_ => Some(Value::Nothing { span: call_span }),
|
||||
|
@ -193,7 +193,9 @@ impl Command for Mv {
|
||||
interactive,
|
||||
);
|
||||
if let Err(error) = result {
|
||||
Some(Value::Error { error })
|
||||
Some(Value::Error {
|
||||
error: Box::new(error),
|
||||
})
|
||||
} else if verbose {
|
||||
let val = match result {
|
||||
Ok(true) => format!(
|
||||
|
@ -405,13 +405,13 @@ fn rm(
|
||||
if let Err(e) = result {
|
||||
let msg = format!("Could not delete because: {e:}");
|
||||
Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
msg,
|
||||
e.to_string(),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
} else if verbose {
|
||||
let msg = if interactive && !confirmed {
|
||||
@ -427,25 +427,25 @@ fn rm(
|
||||
} else {
|
||||
let msg = format!("Cannot remove {:}. try --recursive", f.to_string_lossy());
|
||||
Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
msg,
|
||||
"cannot remove non-empty directory".into(),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let msg = format!("no such file or directory: {:}", f.to_string_lossy());
|
||||
Value::Error {
|
||||
error: ShellError::GenericError(
|
||||
error: Box::new(ShellError::GenericError(
|
||||
msg,
|
||||
"no such file or directory".into(),
|
||||
Some(span),
|
||||
None,
|
||||
Vec::new(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -250,7 +250,7 @@ fn value_to_bytes(value: Value) -> Result<Vec<u8>, ShellError> {
|
||||
Ok(val.into_bytes())
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error),
|
||||
Value::Error { error } => Err(*error),
|
||||
other => Ok(other.as_string()?.into_bytes()),
|
||||
}
|
||||
}
|
||||
@ -376,7 +376,7 @@ fn stream_to_file(
|
||||
Value::String { val, .. } => val.into_bytes(),
|
||||
Value::Binary { val, .. } => val,
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string or binary".into(),
|
||||
|
@ -137,7 +137,7 @@ fn getcol(
|
||||
.into_pipeline_data(ctrlc)
|
||||
.set_metadata(metadata)),
|
||||
// Propagate errors
|
||||
PipelineData::Value(Value::Error { error }, ..) => Err(error),
|
||||
PipelineData::Value(Value::Error { error }, ..) => Err(*error),
|
||||
PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "record or table".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
|
@ -167,7 +167,9 @@ with 'transpose' first."#
|
||||
Err(ShellError::Break(_)) => None,
|
||||
Err(error) => {
|
||||
let error = chain_error_with_input(error, input_span);
|
||||
Some(Value::Error { error })
|
||||
Some(Value::Error {
|
||||
error: Box::new(error),
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -187,7 +189,11 @@ with 'transpose' first."#
|
||||
let x = match x {
|
||||
Ok(x) => x,
|
||||
Err(ShellError::Break(_)) => return None,
|
||||
Err(err) => return Some(Value::Error { error: err }),
|
||||
Err(err) => {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
@ -208,7 +214,7 @@ with 'transpose' first."#
|
||||
Ok(v) => Some(v.into_value(span)),
|
||||
Err(ShellError::Break(_)) => None,
|
||||
Err(error) => {
|
||||
let error = chain_error_with_input(error, input_span);
|
||||
let error = Box::new(chain_error_with_input(error, input_span));
|
||||
Some(Value::Error { error })
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
}
|
||||
}
|
||||
Err(error) => Some(Value::Error {
|
||||
error: chain_error_with_input(error, x.span()),
|
||||
error: Box::new(chain_error_with_input(error, x.span())),
|
||||
}),
|
||||
}
|
||||
})
|
||||
@ -118,7 +118,11 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
|
||||
let x = match x {
|
||||
Ok(x) => x,
|
||||
Err(err) => return Some(Value::Error { error: err }),
|
||||
Err(err) => {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(var) = block.signature.get_positional(0) {
|
||||
@ -144,7 +148,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
}
|
||||
}
|
||||
Err(error) => Some(Value::Error {
|
||||
error: chain_error_with_input(error, x.span()),
|
||||
error: Box::new(chain_error_with_input(error, x.span())),
|
||||
}),
|
||||
}
|
||||
})
|
||||
@ -177,7 +181,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
|
||||
}
|
||||
}
|
||||
Err(error) => Some(Value::Error {
|
||||
error: chain_error_with_input(error, x.span()),
|
||||
error: Box::new(chain_error_with_input(error, x.span())),
|
||||
}),
|
||||
}
|
||||
.into_pipeline_data(ctrlc))
|
||||
|
@ -522,7 +522,7 @@ fn find_with_rest_and_highlight(
|
||||
}
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => return Err(error),
|
||||
Value::Error { error } => return Err(*error),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"unsupported type from raw stream".into(),
|
||||
|
@ -141,7 +141,7 @@ fn first_helper(
|
||||
}
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error),
|
||||
Value::Error { error } => Err(*error),
|
||||
other => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, binary or range".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
|
@ -154,7 +154,7 @@ enum TableInside<'a> {
|
||||
fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) -> Vec<Value> {
|
||||
let tag = match item.span() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return vec![Value::Error { error: e }],
|
||||
Err(e) => return vec![Value::Error { error: Box::new(e) }],
|
||||
};
|
||||
|
||||
let res = {
|
||||
@ -172,19 +172,19 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
|
||||
Value::Error { .. } => return vec![item.clone()],
|
||||
other => {
|
||||
return vec![Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "record".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: _name_tag,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
let s = match item.span() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return vec![Value::Error { error: e }],
|
||||
Err(e) => return vec![Value::Error { error: Box::new(e) }],
|
||||
};
|
||||
|
||||
let records_iterator = {
|
||||
@ -229,12 +229,12 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
|
||||
if all && vals.iter().all(|f| f.as_record().is_ok()) =>
|
||||
{
|
||||
if need_flatten && inner_table.is_some() {
|
||||
return vec![Value::Error{ error: ShellError::UnsupportedInput(
|
||||
return vec![Value::Error{ error: Box::new(ShellError::UnsupportedInput(
|
||||
"can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(),
|
||||
"value originates from here".into(),
|
||||
s,
|
||||
*span
|
||||
)}
|
||||
))}
|
||||
];
|
||||
}
|
||||
// it's a table (a list of record, we can flatten inner record)
|
||||
@ -267,12 +267,12 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
|
||||
}
|
||||
Value::List { vals: values, span } => {
|
||||
if need_flatten && inner_table.is_some() {
|
||||
return vec![Value::Error{ error: ShellError::UnsupportedInput(
|
||||
return vec![Value::Error{ error: Box::new(ShellError::UnsupportedInput(
|
||||
"can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(),
|
||||
"value originates from here".into(),
|
||||
s,
|
||||
*span
|
||||
)}
|
||||
))}
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ pub fn group(
|
||||
Grouper::ByColumn(Some(column_name)) => {
|
||||
let block = Box::new(move |_, row: &Value| {
|
||||
if let Value::Error { error } = row {
|
||||
return Err(error.clone());
|
||||
return Err(*error.clone());
|
||||
};
|
||||
match row.get_data_by_key(&column_name.item) {
|
||||
Some(group_key) => Ok(group_key.as_string()?),
|
||||
|
@ -163,12 +163,12 @@ fn insert(
|
||||
pd.into_value(span),
|
||||
span,
|
||||
) {
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
}
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
},
|
||||
ctrlc,
|
||||
@ -199,7 +199,7 @@ fn insert(
|
||||
if let Err(e) =
|
||||
input.insert_data_at_cell_path(&cell_path.members, replacement, span)
|
||||
{
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
|
@ -86,7 +86,7 @@ fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellErr
|
||||
// Check for and propagate errors
|
||||
for value in input.into_iter() {
|
||||
if let Value::Error { error } = value {
|
||||
return Err(error);
|
||||
return Err(*error);
|
||||
}
|
||||
count += 1
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ impl Command for Lines {
|
||||
PipelineData::Value(val, ..) => {
|
||||
match val {
|
||||
// Propagate existing errors
|
||||
Value::Error { error } => Err(error),
|
||||
Value::Error { error } => Err(*error),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string or raw data".into(),
|
||||
wrong_type: val.get_type().to_string(),
|
||||
@ -129,7 +129,9 @@ impl Command for Lines {
|
||||
.enumerate()
|
||||
.map(move |(_idx, x)| match x {
|
||||
Ok(x) => x,
|
||||
Err(err) => Value::Error { error: err },
|
||||
Err(err) => Value::Error {
|
||||
error: Box::new(err),
|
||||
},
|
||||
})
|
||||
.into_pipeline_data(ctrlc)),
|
||||
}
|
||||
@ -232,7 +234,7 @@ impl Iterator for RawStreamLinesAdapter {
|
||||
self.queue.append(&mut lines);
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => return Some(Err(error)),
|
||||
Value::Error { error } => return Some(Err(*error)),
|
||||
other => {
|
||||
return Some(Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
|
@ -125,11 +125,15 @@ repeating this process with row 1, and so on."#
|
||||
span: call.head,
|
||||
}
|
||||
}
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
}
|
||||
}
|
||||
(_, None) => inp,
|
||||
(Err(error), _) => Value::Error { error },
|
||||
(Err(error), _) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
});
|
||||
|
||||
if let Some(md) = metadata {
|
||||
|
@ -158,9 +158,13 @@ impl Command for Move {
|
||||
call.head,
|
||||
) {
|
||||
Ok(val) => val,
|
||||
Err(error) => Value::Error { error },
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
},
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
},
|
||||
Err(error) => Value::Error { error },
|
||||
});
|
||||
|
||||
if let Some(md) = metadata {
|
||||
|
@ -121,7 +121,7 @@ impl Command for ParEach {
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error {
|
||||
error: chain_error_with_input(error, val_span),
|
||||
error: Box::new(chain_error_with_input(error, val_span)),
|
||||
}
|
||||
.into_pipeline_data(),
|
||||
}
|
||||
@ -155,7 +155,7 @@ impl Command for ParEach {
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error {
|
||||
error: chain_error_with_input(error, val_span),
|
||||
error: Box::new(chain_error_with_input(error, val_span)),
|
||||
}
|
||||
.into_pipeline_data(),
|
||||
}
|
||||
@ -188,7 +188,7 @@ impl Command for ParEach {
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error {
|
||||
error: chain_error_with_input(error, val_span),
|
||||
error: Box::new(chain_error_with_input(error, val_span)),
|
||||
}
|
||||
.into_pipeline_data(),
|
||||
}
|
||||
@ -206,7 +206,12 @@ impl Command for ParEach {
|
||||
.map(move |x| {
|
||||
let x = match x {
|
||||
Ok(x) => x,
|
||||
Err(err) => return Value::Error { error: err }.into_pipeline_data(),
|
||||
Err(err) => {
|
||||
return Value::Error {
|
||||
error: Box::new(err),
|
||||
}
|
||||
.into_pipeline_data()
|
||||
}
|
||||
};
|
||||
|
||||
let block = engine_state.get_block(block_id);
|
||||
@ -228,7 +233,10 @@ impl Command for ParEach {
|
||||
redirect_stderr,
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error { error }.into_pipeline_data(),
|
||||
Err(error) => Value::Error {
|
||||
error: Box::new(error),
|
||||
}
|
||||
.into_pipeline_data(),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
@ -141,7 +141,7 @@ fn rename(
|
||||
// check if the specified column to be renamed exists
|
||||
if !cols.contains(&c[0]) {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
format!(
|
||||
"The column '{}' does not exist in the input",
|
||||
&c[0]
|
||||
@ -151,7 +151,7 @@ fn rename(
|
||||
specified_col_span.unwrap_or(head_span),
|
||||
// Arrow 2 points at the input value.
|
||||
span,
|
||||
),
|
||||
)),
|
||||
};
|
||||
}
|
||||
for (idx, val) in cols.iter_mut().enumerate() {
|
||||
@ -177,12 +177,12 @@ fn rename(
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => item.clone(),
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "record".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head_span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
|
@ -73,7 +73,7 @@ impl Command for Take {
|
||||
.into_pipeline_data(ctrlc)
|
||||
.set_metadata(metadata)),
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error),
|
||||
Value::Error { error } => Err(*error),
|
||||
other => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, binary or range".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
|
@ -132,12 +132,12 @@ fn update(
|
||||
if let Err(e) =
|
||||
input.update_data_at_cell_path(&cell_path.members, pd.into_value(span))
|
||||
{
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
}
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
},
|
||||
ctrlc,
|
||||
@ -174,7 +174,7 @@ fn update(
|
||||
let replacement = replacement.clone();
|
||||
|
||||
if let Err(e) = input.update_data_at_cell_path(&cell_path.members, replacement) {
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
|
@ -253,7 +253,7 @@ fn process_cell(
|
||||
redirect_stderr,
|
||||
) {
|
||||
Ok(pd) => pd.into_value(span),
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,12 +154,12 @@ fn upsert(
|
||||
if let Err(e) =
|
||||
input.upsert_data_at_cell_path(&cell_path.members, pd.into_value(span))
|
||||
{
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
}
|
||||
Err(e) => Value::Error { error: e },
|
||||
Err(e) => Value::Error { error: Box::new(e) },
|
||||
}
|
||||
},
|
||||
ctrlc,
|
||||
@ -195,7 +195,7 @@ fn upsert(
|
||||
let replacement = replacement.clone();
|
||||
|
||||
if let Err(e) = input.upsert_data_at_cell_path(&cell_path.members, replacement) {
|
||||
return Value::Error { error: e };
|
||||
return Value::Error { error: Box::new(e) };
|
||||
}
|
||||
|
||||
input
|
||||
|
@ -119,7 +119,7 @@ pub fn get_values<'a>(
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
_ => {
|
||||
return Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "record or table".into(),
|
||||
@ -176,7 +176,7 @@ fn values(
|
||||
Ok(vals.into_pipeline_data(ctrlc).set_metadata(metadata))
|
||||
}
|
||||
// Propagate errors
|
||||
PipelineData::Value(Value::Error { error }, ..) => Err(error),
|
||||
PipelineData::Value(Value::Error { error }, ..) => Err(*error),
|
||||
PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "record or table".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
|
@ -97,7 +97,9 @@ not supported."#
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(err) => Some(Value::Error { error: err }),
|
||||
Err(err) => Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
}),
|
||||
}
|
||||
})
|
||||
.into_pipeline_data(ctrlc)
|
||||
|
@ -77,7 +77,9 @@ impl Command for FromJson {
|
||||
} else {
|
||||
match convert_string_to_value(x.to_string(), span) {
|
||||
Ok(v) => Some(v),
|
||||
Err(error) => Some(Value::Error { error }),
|
||||
Err(error) => Some(Value::Error {
|
||||
error: Box::new(error),
|
||||
}),
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -119,12 +121,12 @@ fn convert_nujson_to_value(value: &nu_json::Value, span: Span) -> Value {
|
||||
nu_json::Value::U64(u) => {
|
||||
if *u > i64::MAX as u64 {
|
||||
Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "i64 sized integer".into(),
|
||||
from_type: "value larger than i64".into(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
Value::Int {
|
||||
|
@ -93,7 +93,7 @@ fn collect_binary(input: PipelineData, span: Span) -> Result<Vec<u8>, ShellError
|
||||
Some(Value::Binary { val: b, .. }) => {
|
||||
bytes.extend_from_slice(&b);
|
||||
}
|
||||
Some(Value::Error { error }) => return Err(error),
|
||||
Some(Value::Error { error }) => return Err(*error),
|
||||
Some(x) => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Expected binary from pipeline".to_string(),
|
||||
|
@ -16,7 +16,7 @@ fn from_value_to_delimited_string(
|
||||
}
|
||||
Value::List { vals, span } => table_to_delimited(vals, span, separator, config, head),
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
v => Err(make_unsupported_input_error(v, head, v.expect_span())),
|
||||
}
|
||||
}
|
||||
@ -122,7 +122,7 @@ fn to_string_tagged_value(
|
||||
Value::Date { val, .. } => Ok(val.to_string()),
|
||||
Value::Nothing { .. } => Ok(String::new()),
|
||||
// Propagate existing errors
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
_ => Err(make_unsupported_input_error(v, head, span)),
|
||||
}
|
||||
}
|
||||
|
@ -70,12 +70,12 @@ impl Command for ToJson {
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
_ => Ok(Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "JSON".into(),
|
||||
from_type: value.get_type().to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
}
|
||||
@ -126,7 +126,7 @@ pub fn value_to_json_value(v: &Value) -> Result<nu_json::Value, ShellError> {
|
||||
),
|
||||
|
||||
Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?),
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
|
||||
Value::Binary { val, .. } => {
|
||||
nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect())
|
||||
|
@ -101,7 +101,7 @@ pub fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
|
||||
// FIXME: make durations use the shortest lossless representation.
|
||||
Value::Duration { val, .. } => Ok(format!("{}ns", *val)),
|
||||
// Propagate existing errors
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
// FIXME: make filesizes use the shortest lossless representation.
|
||||
Value::Filesize { val, .. } => Ok(format!("{}b", *val)),
|
||||
Value::Float { val, .. } => {
|
||||
|
@ -77,7 +77,7 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result<toml::Value, ShellErr
|
||||
toml::Value::String(code)
|
||||
}
|
||||
Value::Nothing { .. } => toml::Value::String("<Nothing>".to_string()),
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
Value::Binary { val, .. } => toml::Value::Array(
|
||||
val.iter()
|
||||
.map(|x| toml::Value::Integer(*x as i64))
|
||||
@ -118,12 +118,12 @@ fn toml_into_pipeline_data(
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
_ => Ok(Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "TOML".into(),
|
||||
from_type: value_type.to_string(),
|
||||
span,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
}
|
||||
@ -137,7 +137,7 @@ fn value_to_toml_value(
|
||||
match v {
|
||||
Value::Record { .. } => helper(engine_state, v),
|
||||
// Propagate existing errors
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
_ => Err(ShellError::UnsupportedInput(
|
||||
format!("{:?} is not valid top-level TOML", v.get_type()),
|
||||
"value originates from here".into(),
|
||||
|
@ -79,7 +79,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
|
||||
Value::Block { .. } => serde_yaml::Value::Null,
|
||||
Value::Closure { .. } => serde_yaml::Value::Null,
|
||||
Value::Nothing { .. } => serde_yaml::Value::Null,
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
Value::Binary { val, .. } => serde_yaml::Value::Sequence(
|
||||
val.iter()
|
||||
.map(|x| serde_yaml::Value::Number(serde_yaml::Number::from(*x)))
|
||||
@ -111,12 +111,12 @@ fn to_yaml(input: PipelineData, head: Span) -> Result<PipelineData, ShellError>
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
_ => Ok(Value::Error {
|
||||
error: ShellError::CantConvert {
|
||||
error: Box::new(ShellError::CantConvert {
|
||||
to_type: "YAML".into(),
|
||||
from_type: value.get_type().to_string(),
|
||||
span: head,
|
||||
help: None,
|
||||
},
|
||||
}),
|
||||
}
|
||||
.into_pipeline_data()),
|
||||
}
|
||||
|
@ -111,16 +111,20 @@ where
|
||||
other => {
|
||||
let span = match input.span() {
|
||||
Ok(span) => span,
|
||||
Err(error) => return Value::Error { error },
|
||||
Err(error) => {
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string or binary".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -76,7 +76,9 @@ where
|
||||
}),
|
||||
);
|
||||
if let Err(error) = r {
|
||||
return Value::Error { error };
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
v
|
||||
|
@ -68,12 +68,12 @@ fn abs_helper(val: Value, head: Span) -> Value {
|
||||
},
|
||||
Value::Error { .. } => val,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -77,23 +77,23 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
Value::Float { val, span }
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'arccos' undefined for values outside the closed interval [-1, 1].".into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
Value::Float { val, span }
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'arccosh' undefined for values below 1.".into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -78,23 +78,23 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
Value::Float { val, span }
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'arcsin' undefined for values outside the closed interval [-1, 1].".into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +67,12 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -78,12 +78,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
Value::Float { val, span }
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'arctanh' undefined for values outside the open interval (-1, 1).".into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
},
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -88,12 +88,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
},
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
Value::Float { val, span }
|
||||
} else {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'ln' undefined for values outside the open interval (0, Inf).".into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -96,13 +96,13 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
|
||||
|
||||
if val <= 0.0 {
|
||||
return Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"'math log' undefined for values outside the open interval (0, Inf)."
|
||||
.into(),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
};
|
||||
}
|
||||
// Specialize for better precision/performance
|
||||
@ -118,12 +118,12 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ pub fn mode(values: &[Value], _span: Span, head: &Span) -> Result<Value, ShellEr
|
||||
Value::Filesize { val, .. } => {
|
||||
Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Filesize))
|
||||
}
|
||||
Value::Error { error } => Err(error.clone()),
|
||||
Value::Error { error } => Err(*error.clone()),
|
||||
other => Err(ShellError::UnsupportedInput(
|
||||
"Unable to give a result with this input".to_string(),
|
||||
"value originates from here".into(),
|
||||
|
@ -112,7 +112,7 @@ pub fn sum(data: Vec<Value>, span: Span, head: Span) -> Result<Value, ShellError
|
||||
| Value::Duration { .. } => {
|
||||
acc = acc.add(head, value, head)?;
|
||||
}
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Attempted to compute the sum of a value that cannot be summed".to_string(),
|
||||
@ -145,7 +145,7 @@ pub fn product(data: Vec<Value>, span: Span, head: Span) -> Result<Value, ShellE
|
||||
Value::Int { .. } | Value::Float { .. } => {
|
||||
acc = acc.mul(head, value, head)?;
|
||||
}
|
||||
Value::Error { error } => return Err(error.clone()),
|
||||
Value::Error { error } => return Err(*error.clone()),
|
||||
other => {
|
||||
return Err(ShellError::UnsupportedInput(
|
||||
"Attempted to compute the product of a value that cannot be multiplied"
|
||||
|
@ -95,12 +95,12 @@ fn operate(value: Value, head: Span, precision: Option<i64>) -> Value {
|
||||
Value::Int { .. } => value,
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -88,12 +88,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -73,24 +73,24 @@ fn operate(value: Value, head: Span) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn error_negative_sqrt(head: Span, span: Span) -> Value {
|
||||
Value::Error {
|
||||
error: ShellError::UnsupportedInput(
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
String::from("Can't square root a negative number"),
|
||||
"value originates from here".into(),
|
||||
head,
|
||||
span,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,12 +86,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
|
||||
}
|
||||
Value::Error { .. } => value,
|
||||
other => Value::Error {
|
||||
error: ShellError::OnlySupportsThisInputType {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "numeric".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: other.expect_span(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user