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