nu_command/bytes/
length.rs

1use nu_cmd_base::input_handler::{CellPathOnlyArgs, operate};
2use nu_engine::command_prelude::*;
3
4#[derive(Clone)]
5pub struct BytesLen;
6
7impl Command for BytesLen {
8    fn name(&self) -> &str {
9        "bytes length"
10    }
11
12    fn signature(&self) -> Signature {
13        Signature::build("bytes length")
14            .input_output_types(vec![
15                (Type::Binary, Type::Int),
16                (
17                    Type::List(Box::new(Type::Binary)),
18                    Type::List(Box::new(Type::Int)),
19                ),
20                (Type::table(), Type::table()),
21                (Type::record(), Type::record()),
22            ])
23            .allow_variants_without_examples(true)
24            .rest(
25                "rest",
26                SyntaxShape::CellPath,
27                "For a data structure input, find the length of data at the given cell paths.",
28            )
29            .category(Category::Bytes)
30    }
31
32    fn description(&self) -> &str {
33        "Output the length of any bytes in the pipeline."
34    }
35
36    fn search_terms(&self) -> Vec<&str> {
37        vec!["size", "count"]
38    }
39
40    fn run(
41        &self,
42        engine_state: &EngineState,
43        stack: &mut Stack,
44        call: &Call,
45        input: PipelineData,
46    ) -> Result<PipelineData, ShellError> {
47        let cell_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
48        let arg = CellPathOnlyArgs::from(cell_paths);
49        operate(length, arg, input, call.head, engine_state.signals())
50    }
51
52    fn examples(&self) -> Vec<Example<'_>> {
53        vec![
54            Example {
55                description: "Return the length of a binary",
56                example: "0x[1F FF AA AB] | bytes length",
57                result: Some(Value::test_int(4)),
58            },
59            Example {
60                description: "Return the lengths of multiple binaries",
61                example: "[0x[1F FF AA AB] 0x[1F]] | bytes length",
62                result: Some(Value::list(
63                    vec![Value::test_int(4), Value::test_int(1)],
64                    Span::test_data(),
65                )),
66            },
67        ]
68    }
69
70    fn is_const(&self) -> bool {
71        true
72    }
73
74    fn run_const(
75        &self,
76        working_set: &StateWorkingSet,
77        call: &Call,
78        input: PipelineData,
79    ) -> Result<PipelineData, ShellError> {
80        let cell_paths: Vec<CellPath> = call.rest_const(working_set, 0)?;
81        let arg = CellPathOnlyArgs::from(cell_paths);
82        operate(
83            length,
84            arg,
85            input,
86            call.head,
87            working_set.permanent().signals(),
88        )
89    }
90}
91
92fn length(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
93    let val_span = val.span();
94    match val {
95        Value::Binary { val, .. } => Value::int(val.len() as i64, val_span),
96        // Propagate errors by explicitly matching them before the final case.
97        Value::Error { .. } => val.clone(),
98        other => Value::error(
99            ShellError::OnlySupportsThisInputType {
100                exp_input_type: "binary".into(),
101                wrong_type: other.get_type().to_string(),
102                dst_span: span,
103                src_span: other.span(),
104            },
105            span,
106        ),
107    }
108}
109
110#[cfg(test)]
111mod test {
112    use super::*;
113
114    #[test]
115    fn test_examples() {
116        use crate::test_examples;
117
118        test_examples(BytesLen {})
119    }
120}