Skip to content

Commit 5f04bbb

Browse files
authored
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 ╰──── ```
1 parent 49fb5cb commit 5f04bbb

File tree

1 file changed

+20
-23
lines changed

1 file changed

+20
-23
lines changed

crates/nu-command/src/filters/length.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl Command for Length {
1919
.input_output_types(vec![
2020
(Type::List(Box::new(Type::Any)), Type::Int),
2121
(Type::Binary, Type::Int),
22+
(Type::Nothing, Type::Int),
2223
])
2324
.category(Category::Filters)
2425
}
@@ -54,30 +55,31 @@ impl Command for Length {
5455
example: "0x[01 02] | length",
5556
result: Some(Value::test_int(2)),
5657
},
58+
Example {
59+
description: "Count the length a null value",
60+
example: "null | length",
61+
result: Some(Value::test_int(0)),
62+
},
5763
]
5864
}
5965
}
6066

6167
fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellError> {
6268
let span = input.span().unwrap_or(call.head);
6369
match input {
64-
PipelineData::Value(Value::Nothing { .. }, ..) => {
70+
PipelineData::Empty | PipelineData::Value(Value::Nothing { .. }, ..) => {
6571
Ok(Value::int(0, call.head).into_pipeline_data())
6672
}
67-
// I added this here because input_output_type() wasn't catching a record
68-
// being sent in as input from echo. e.g. "echo {a:1 b:2} | length"
69-
PipelineData::Value(Value::Record { .. }, ..) => {
70-
Err(ShellError::OnlySupportsThisInputType {
71-
exp_input_type: "list, and table".into(),
72-
wrong_type: "record".into(),
73-
dst_span: call.head,
74-
src_span: span,
75-
})
76-
}
7773
PipelineData::Value(Value::Binary { val, .. }, ..) => {
7874
Ok(Value::int(val.len() as i64, call.head).into_pipeline_data())
7975
}
80-
PipelineData::ByteStream(stream, _) if stream.type_().is_binary_coercible() => {
76+
PipelineData::Value(Value::List { vals, .. }, ..) => {
77+
Ok(Value::int(vals.len() as i64, call.head).into_pipeline_data())
78+
}
79+
PipelineData::ListStream(stream, ..) => {
80+
Ok(Value::int(stream.into_iter().count() as i64, call.head).into_pipeline_data())
81+
}
82+
PipelineData::ByteStream(stream, ..) if stream.type_().is_binary_coercible() => {
8183
Ok(Value::int(
8284
match stream.reader() {
8385
Some(r) => r.bytes().count() as i64,
@@ -87,17 +89,12 @@ fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellErr
8789
)
8890
.into_pipeline_data())
8991
}
90-
_ => {
91-
let mut count: i64 = 0;
92-
// Check for and propagate errors
93-
for value in input.into_iter() {
94-
if let Value::Error { error, .. } = value {
95-
return Err(*error);
96-
}
97-
count += 1
98-
}
99-
Ok(Value::int(count, call.head).into_pipeline_data())
100-
}
92+
_ => Err(ShellError::OnlySupportsThisInputType {
93+
exp_input_type: "list, table, binary, and nothing".into(),
94+
wrong_type: input.get_type().to_string(),
95+
dst_span: call.head,
96+
src_span: span,
97+
}),
10198
}
10299
}
103100

0 commit comments

Comments
 (0)