nu_command/bytes/
split.rs1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct BytesSplit;
5
6impl Command for BytesSplit {
7 fn name(&self) -> &str {
8 "bytes split"
9 }
10
11 fn signature(&self) -> Signature {
12 Signature::build("bytes split")
13 .input_output_types(vec![(Type::Binary, Type::list(Type::Binary))])
14 .required(
15 "separator",
16 SyntaxShape::OneOf(vec![SyntaxShape::Binary, SyntaxShape::String]),
17 "Bytes or string that the input will be split on (must be non-empty).",
18 )
19 .category(Category::Bytes)
20 }
21
22 fn description(&self) -> &str {
23 "Split input into multiple items using a separator."
24 }
25
26 fn search_terms(&self) -> Vec<&str> {
27 vec!["separate", "stream"]
28 }
29
30 fn examples(&self) -> Vec<Example> {
31 vec![
32 Example {
33 example: r#"0x[66 6F 6F 20 62 61 72 20 62 61 7A 20] | bytes split 0x[20]"#,
34 description: "Split a binary value using a binary separator",
35 result: Some(Value::test_list(vec![
36 Value::test_binary("foo"),
37 Value::test_binary("bar"),
38 Value::test_binary("baz"),
39 Value::test_binary(""),
40 ])),
41 },
42 Example {
43 example: r#"0x[61 2D 2D 62 2D 2D 63] | bytes split "--""#,
44 description: "Split a binary value using a string separator",
45 result: Some(Value::test_list(vec![
46 Value::test_binary("a"),
47 Value::test_binary("b"),
48 Value::test_binary("c"),
49 ])),
50 },
51 ]
52 }
53
54 fn run(
55 &self,
56 engine_state: &EngineState,
57 stack: &mut Stack,
58 call: &Call,
59 input: PipelineData,
60 ) -> Result<PipelineData, ShellError> {
61 let head = call.head;
62 let Spanned {
63 item: separator,
64 span,
65 }: Spanned<Vec<u8>> = call.req(engine_state, stack, 0)?;
66
67 if separator.is_empty() {
68 return Err(ShellError::IncorrectValue {
69 msg: "Separator can't be empty".into(),
70 val_span: span,
71 call_span: call.head,
72 });
73 }
74
75 let (split_read, md) = match input {
76 PipelineData::Value(Value::Binary { val, .. }, md) => (
77 ByteStream::read_binary(val, head, engine_state.signals().clone()).split(separator),
78 md,
79 ),
80 PipelineData::ByteStream(stream, md) => (stream.split(separator), md),
81 input => {
82 let span = input.span().unwrap_or(head);
83 return Err(input.unsupported_input_error("bytes", span));
84 }
85 };
86 if let Some(split) = split_read {
87 Ok(split
88 .map(move |part| match part {
89 Ok(val) => Value::binary(val, head),
90 Err(err) => Value::error(err, head),
91 })
92 .into_pipeline_data_with_metadata(head, engine_state.signals().clone(), md))
93 } else {
94 Ok(PipelineData::empty())
95 }
96 }
97}
98
99#[cfg(test)]
100mod test {
101 use super::*;
102
103 #[test]
104 fn test_examples() {
105 use crate::test_examples;
106
107 test_examples(BytesSplit {})
108 }
109}