nu_cmd_extra/extra/bits/
and.rs1use super::binary_op;
2use nu_engine::command_prelude::*;
3
4#[derive(Clone)]
5pub struct BitsAnd;
6
7impl Command for BitsAnd {
8 fn name(&self) -> &str {
9 "bits and"
10 }
11
12 fn signature(&self) -> Signature {
13 Signature::build("bits and")
14 .input_output_types(vec![
15 (Type::Int, Type::Int),
16 (Type::Binary, Type::Binary),
17 (
18 Type::List(Box::new(Type::Int)),
19 Type::List(Box::new(Type::Int)),
20 ),
21 (
22 Type::List(Box::new(Type::Binary)),
23 Type::List(Box::new(Type::Binary)),
24 ),
25 ])
26 .required(
27 "target",
28 SyntaxShape::OneOf(vec![SyntaxShape::Binary, SyntaxShape::Int]),
29 "Right-hand side of the operation.",
30 )
31 .named(
32 "endian",
33 SyntaxShape::String,
34 "byte encode endian, available options: native(default), little, big",
35 Some('e'),
36 )
37 .category(Category::Bits)
38 }
39
40 fn description(&self) -> &str {
41 "Performs bitwise and for ints or binary values."
42 }
43
44 fn search_terms(&self) -> Vec<&str> {
45 vec!["logic and"]
46 }
47
48 fn run(
49 &self,
50 engine_state: &EngineState,
51 stack: &mut Stack,
52 call: &Call,
53 input: PipelineData,
54 ) -> Result<PipelineData, ShellError> {
55 let head = call.head;
56 let target: Value = call.req(engine_state, stack, 0)?;
57 let endian = call.get_flag::<Spanned<String>>(engine_state, stack, "endian")?;
58
59 let little_endian = if let Some(endian) = endian {
60 match endian.item.as_str() {
61 "native" => cfg!(target_endian = "little"),
62 "little" => true,
63 "big" => false,
64 _ => {
65 return Err(ShellError::TypeMismatch {
66 err_message: "Endian must be one of native, little, big".to_string(),
67 span: endian.span,
68 });
69 }
70 }
71 } else {
72 cfg!(target_endian = "little")
73 };
74
75 if let PipelineData::Empty = input {
77 return Err(ShellError::PipelineEmpty { dst_span: head });
78 }
79
80 input.map(
81 move |value| binary_op(&value, &target, little_endian, |(l, r)| l & r, head),
82 engine_state.signals(),
83 )
84 }
85
86 fn examples(&self) -> Vec<Example<'_>> {
87 vec![
88 Example {
89 description: "Apply bitwise and to two numbers",
90 example: "2 | bits and 2",
91 result: Some(Value::test_int(2)),
92 },
93 Example {
94 description: "Apply bitwise and to two binary values",
95 example: "0x[ab cd] | bits and 0x[99 99]",
96 result: Some(Value::test_binary([0x89, 0x89])),
97 },
98 Example {
99 description: "Apply bitwise and to a list of numbers",
100 example: "[4 3 2] | bits and 2",
101 result: Some(Value::test_list(vec![
102 Value::test_int(0),
103 Value::test_int(2),
104 Value::test_int(2),
105 ])),
106 },
107 Example {
108 description: "Apply bitwise and to a list of binary data",
109 example: "[0x[7f ff] 0x[ff f0]] | bits and 0x[99 99]",
110 result: Some(Value::test_list(vec![
111 Value::test_binary([0x19, 0x99]),
112 Value::test_binary([0x99, 0x90]),
113 ])),
114 },
115 Example {
116 description: "Apply bitwise and to binary data of varying lengths with specified endianness",
117 example: "0x[c0 ff ee] | bits and 0x[ff] --endian big",
118 result: Some(Value::test_binary(vec![0x00, 0x00, 0xee])),
119 },
120 Example {
121 description: "Apply bitwise and to input binary data smaller than the operand",
122 example: "0x[ff] | bits and 0x[12 34 56] --endian little",
123 result: Some(Value::test_binary(vec![0x12, 0x00, 0x00])),
124 },
125 ]
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132
133 #[test]
134 fn test_examples() {
135 use crate::test_examples;
136
137 test_examples(BitsAnd {})
138 }
139}