mirror of
https://github.com/nushell/nushell
synced 2024-12-25 12:33:17 +00:00
Make length only operate on supported input types (#14475)
# Description Before this PR, `length` did not check its input type at run-time, so it would attempt to calculate a length for any input with indeterminate type (e.g., `echo` which has an `any` output type). This PR makes `length` only work on the types specifically supported in its input/output types (list/table, binary, and nothing), making the behavior the same at parse-time and at run-time. Fixes #14462 # User-Facing Changes Length will error if passed an unsupported type: Before (only caught at parse-time): ```nushell "hello" | length Error: nu::parser::input_type_mismatch × Command does not support string input. ╭─[entry #2:1:11] 1 │ "hello" | length · ───┬── · ╰── command doesn't support string input ╰──── echo "hello" | length # => 1 ``` After (caught at parse-time and run-time): ```nushell "hello" | length Error: nu::parser::input_type_mismatch × Command does not support string input. ╭─[entry #22:1:11] 1 │ "hello" | length · ───┬── · ╰── command doesn't support string input ╰──── echo "hello" | length Error: nu:🐚:only_supports_this_input_type × Input type not supported. ╭─[entry #23:1:6] 1 │ echo "hello" | length · ───┬─── ───┬── · │ ╰── only list, table, binary, and nothing input data is supported · ╰── input type: string ╰──── ```
This commit is contained in:
parent
49fb5cb1a8
commit
5f04bbbb8b
1 changed files with 20 additions and 23 deletions
|
@ -19,6 +19,7 @@ impl Command for Length {
|
|||
.input_output_types(vec![
|
||||
(Type::List(Box::new(Type::Any)), Type::Int),
|
||||
(Type::Binary, Type::Int),
|
||||
(Type::Nothing, Type::Int),
|
||||
])
|
||||
.category(Category::Filters)
|
||||
}
|
||||
|
@ -54,6 +55,11 @@ impl Command for Length {
|
|||
example: "0x[01 02] | length",
|
||||
result: Some(Value::test_int(2)),
|
||||
},
|
||||
Example {
|
||||
description: "Count the length a null value",
|
||||
example: "null | length",
|
||||
result: Some(Value::test_int(0)),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -61,23 +67,19 @@ impl Command for Length {
|
|||
fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellError> {
|
||||
let span = input.span().unwrap_or(call.head);
|
||||
match input {
|
||||
PipelineData::Value(Value::Nothing { .. }, ..) => {
|
||||
PipelineData::Empty | PipelineData::Value(Value::Nothing { .. }, ..) => {
|
||||
Ok(Value::int(0, call.head).into_pipeline_data())
|
||||
}
|
||||
// I added this here because input_output_type() wasn't catching a record
|
||||
// being sent in as input from echo. e.g. "echo {a:1 b:2} | length"
|
||||
PipelineData::Value(Value::Record { .. }, ..) => {
|
||||
Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, and table".into(),
|
||||
wrong_type: "record".into(),
|
||||
dst_span: call.head,
|
||||
src_span: span,
|
||||
})
|
||||
}
|
||||
PipelineData::Value(Value::Binary { val, .. }, ..) => {
|
||||
Ok(Value::int(val.len() as i64, call.head).into_pipeline_data())
|
||||
}
|
||||
PipelineData::ByteStream(stream, _) if stream.type_().is_binary_coercible() => {
|
||||
PipelineData::Value(Value::List { vals, .. }, ..) => {
|
||||
Ok(Value::int(vals.len() as i64, call.head).into_pipeline_data())
|
||||
}
|
||||
PipelineData::ListStream(stream, ..) => {
|
||||
Ok(Value::int(stream.into_iter().count() as i64, call.head).into_pipeline_data())
|
||||
}
|
||||
PipelineData::ByteStream(stream, ..) if stream.type_().is_binary_coercible() => {
|
||||
Ok(Value::int(
|
||||
match stream.reader() {
|
||||
Some(r) => r.bytes().count() as i64,
|
||||
|
@ -87,17 +89,12 @@ fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellErr
|
|||
)
|
||||
.into_pipeline_data())
|
||||
}
|
||||
_ => {
|
||||
let mut count: i64 = 0;
|
||||
// Check for and propagate errors
|
||||
for value in input.into_iter() {
|
||||
if let Value::Error { error, .. } = value {
|
||||
return Err(*error);
|
||||
}
|
||||
count += 1
|
||||
}
|
||||
Ok(Value::int(count, call.head).into_pipeline_data())
|
||||
}
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, table, binary, and nothing".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: call.head,
|
||||
src_span: span,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue