nu_command/strings/base/
base32hex.rs1use nu_engine::command_prelude::*;
2
3const EXTRA_USAGE: &str = r"This command uses an alternative Base32 alphabet, defined in RFC 4648, section 7.
4
5Note this command will collect stream input.";
6
7#[derive(Clone)]
8pub struct DecodeBase32Hex;
9
10impl Command for DecodeBase32Hex {
11 fn name(&self) -> &str {
12 "decode base32hex"
13 }
14
15 fn signature(&self) -> Signature {
16 Signature::build("decode base32hex")
17 .input_output_types(vec![(Type::String, Type::Binary)])
18 .allow_variants_without_examples(true)
19 .switch("nopad", "Reject input with padding.", None)
20 .category(Category::Formats)
21 }
22
23 fn description(&self) -> &str {
24 "Encode a base32hex value."
25 }
26
27 fn extra_description(&self) -> &str {
28 EXTRA_USAGE
29 }
30
31 fn examples(&self) -> Vec<Example> {
32 vec![
33 Example {
34 description: "Decode arbitrary binary data",
35 example: r#""ATNAQ===" | decode base32hex"#,
36 result: Some(Value::test_binary(vec![0x57, 0x6E, 0xAD])),
37 },
38 Example {
39 description: "Decode an encoded string",
40 example: r#""D1KG====" | decode base32hex | decode"#,
41 result: None,
42 },
43 Example {
44 description: "Parse a string without padding",
45 example: r#""ATNAQ" | decode base32hex --nopad"#,
46 result: Some(Value::test_binary(vec![0x57, 0x6E, 0xAD])),
47 },
48 ]
49 }
50
51 fn is_const(&self) -> bool {
52 true
53 }
54
55 fn run(
56 &self,
57 engine_state: &EngineState,
58 stack: &mut Stack,
59 call: &Call,
60 input: PipelineData,
61 ) -> Result<PipelineData, ShellError> {
62 let encoding = if call.has_flag(engine_state, stack, "nopad")? {
63 data_encoding::BASE32HEX_NOPAD
64 } else {
65 data_encoding::BASE32HEX
66 };
67
68 super::decode(encoding, call.head, input)
69 }
70
71 fn run_const(
72 &self,
73 working_set: &StateWorkingSet,
74 call: &Call,
75 input: PipelineData,
76 ) -> Result<PipelineData, ShellError> {
77 let encoding = if call.has_flag_const(working_set, "nopad")? {
78 data_encoding::BASE32HEX_NOPAD
79 } else {
80 data_encoding::BASE32HEX
81 };
82
83 super::decode(encoding, call.head, input)
84 }
85}
86
87#[derive(Clone)]
88pub struct EncodeBase32Hex;
89
90impl Command for EncodeBase32Hex {
91 fn name(&self) -> &str {
92 "encode base32hex"
93 }
94
95 fn signature(&self) -> Signature {
96 Signature::build("encode base32hex")
97 .input_output_types(vec![
98 (Type::String, Type::String),
99 (Type::Binary, Type::String),
100 ])
101 .switch("nopad", "Don't pad the output.", None)
102 .category(Category::Formats)
103 }
104
105 fn description(&self) -> &str {
106 "Encode a binary value or a string using base32hex."
107 }
108
109 fn extra_description(&self) -> &str {
110 EXTRA_USAGE
111 }
112
113 fn examples(&self) -> Vec<Example> {
114 vec![
115 Example {
116 description: "Encode a binary value",
117 example: r#"0x[57 6E AD] | encode base32hex"#,
118 result: Some(Value::test_string("ATNAQ===")),
119 },
120 Example {
121 description: "Encode a string",
122 example: r#""hello there" | encode base32hex"#,
123 result: Some(Value::test_string("D1IMOR3F41Q6GPBICK======")),
124 },
125 Example {
126 description: "Don't apply padding to the output",
127 example: r#""hello there" | encode base32hex --nopad"#,
128 result: Some(Value::test_string("D1IMOR3F41Q6GPBICK")),
129 },
130 ]
131 }
132
133 fn is_const(&self) -> bool {
134 true
135 }
136
137 fn run(
138 &self,
139 engine_state: &EngineState,
140 stack: &mut Stack,
141 call: &Call,
142 input: PipelineData,
143 ) -> Result<PipelineData, ShellError> {
144 let encoding = if call.has_flag(engine_state, stack, "nopad")? {
145 data_encoding::BASE32HEX_NOPAD
146 } else {
147 data_encoding::BASE32HEX
148 };
149
150 super::encode(encoding, call.head, input)
151 }
152
153 fn run_const(
154 &self,
155 working_set: &StateWorkingSet,
156 call: &Call,
157 input: PipelineData,
158 ) -> Result<PipelineData, ShellError> {
159 let encoding = if call.has_flag_const(working_set, "nopad")? {
160 data_encoding::BASE32HEX_NOPAD
161 } else {
162 data_encoding::BASE32HEX
163 };
164
165 super::encode(encoding, call.head, input)
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_examples_decode() {
175 crate::test_examples(DecodeBase32Hex)
176 }
177 #[test]
178 fn test_examples_encode() {
179 crate::test_examples(EncodeBase32Hex)
180 }
181}