nu_command/strings/encode_decode/
encode.rs1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct Encode;
5
6impl Command for Encode {
7 fn name(&self) -> &str {
8 "encode"
9 }
10
11 fn description(&self) -> &str {
12 "Encode a string into bytes."
17 }
18
19 fn search_terms(&self) -> Vec<&str> {
20 vec!["text", "encoding", "decoding"]
21 }
22
23 fn signature(&self) -> nu_protocol::Signature {
24 Signature::build("encode")
25 .input_output_types(vec![(Type::String, Type::Binary)])
26 .required("encoding", SyntaxShape::String, "The text encoding to use.")
27 .switch(
28 "ignore-errors",
29 "when a character isn't in the given encoding, replace with a HTML entity (like `🎈`)",
30 Some('i'),
31 )
32 .category(Category::Strings)
33 }
34
35 fn extra_description(&self) -> &str {
36 r#"Multiple encodings are supported; here are a few:
37big5, euc-jp, euc-kr, gbk, iso-8859-1, cp1252, latin5
38
39Note that since the Encoding Standard doesn't specify encoders for utf-16le and utf-16be, these are not yet supported.
40More information can be found here: https://docs.rs/encoding_rs/latest/encoding_rs/#utf-16le-utf-16be-and-unicode-encoding-schemes
41
42For a more complete list of encodings, please refer to the encoding_rs
43documentation link at https://docs.rs/encoding_rs/latest/encoding_rs/#statics"#
44 }
45
46 fn examples(&self) -> Vec<Example> {
47 vec![
48 Example {
49 description: "Encode an UTF-8 string into Shift-JIS",
50 example: r#""負けると知って戦うのが、遥かに美しいのだ" | encode shift-jis"#,
51 result: Some(Value::binary(
52 vec![
53 0x95, 0x89, 0x82, 0xaf, 0x82, 0xe9, 0x82, 0xc6, 0x92, 0x6d, 0x82, 0xc1,
54 0x82, 0xc4, 0x90, 0xed, 0x82, 0xa4, 0x82, 0xcc, 0x82, 0xaa, 0x81, 0x41,
55 0x97, 0x79, 0x82, 0xa9, 0x82, 0xc9, 0x94, 0xfc, 0x82, 0xb5, 0x82, 0xa2,
56 0x82, 0xcc, 0x82, 0xbe,
57 ],
58 Span::test_data(),
59 )),
60 },
61 Example {
62 description: "Replace characters with HTML entities if they can't be encoded",
63 example: r#""🎈" | encode --ignore-errors shift-jis"#,
64 result: Some(Value::binary(
65 vec![0x26, 0x23, 0x31, 0x32, 0x37, 0x38, 0x38, 0x30, 0x3b],
66 Span::test_data(),
67 )),
68 },
69 ]
70 }
71
72 fn is_const(&self) -> bool {
73 true
74 }
75
76 fn run(
77 &self,
78 engine_state: &EngineState,
79 stack: &mut Stack,
80 call: &Call,
81 input: PipelineData,
82 ) -> Result<PipelineData, ShellError> {
83 let encoding: Spanned<String> = call.req(engine_state, stack, 0)?;
84 let ignore_errors = call.has_flag(engine_state, stack, "ignore-errors")?;
85 run(call, input, encoding, ignore_errors)
86 }
87
88 fn run_const(
89 &self,
90 working_set: &StateWorkingSet,
91 call: &Call,
92 input: PipelineData,
93 ) -> Result<PipelineData, ShellError> {
94 let encoding: Spanned<String> = call.req_const(working_set, 0)?;
95 let ignore_errors = call.has_flag_const(working_set, "ignore-errors")?;
96 run(call, input, encoding, ignore_errors)
97 }
98}
99
100fn run(
101 call: &Call,
102 input: PipelineData,
103 encoding: Spanned<String>,
104 ignore_errors: bool,
105) -> Result<PipelineData, ShellError> {
106 let head = call.head;
107
108 match input {
109 PipelineData::ByteStream(stream, ..) => {
110 let span = stream.span();
111 let s = stream.into_string()?;
112 super::encoding::encode(head, encoding, &s, span, ignore_errors)
113 .map(|val| val.into_pipeline_data())
114 }
115 PipelineData::Value(v, ..) => {
116 let span = v.span();
117 match v {
118 Value::String { val: s, .. } => {
119 super::encoding::encode(head, encoding, &s, span, ignore_errors)
120 .map(|val| val.into_pipeline_data())
121 }
122 Value::Error { error, .. } => Err(*error),
123 _ => Err(ShellError::OnlySupportsThisInputType {
124 exp_input_type: "string".into(),
125 wrong_type: v.get_type().to_string(),
126 dst_span: head,
127 src_span: v.span(),
128 }),
129 }
130 }
131 _ => Err(ShellError::UnsupportedInput {
134 msg: "non-string input".into(),
135 input: "value originates from here".into(),
136 msg_span: head,
137 input_span: input.span().unwrap_or(head),
138 }),
139 }
140}
141
142#[cfg(test)]
143mod test {
144 use super::*;
145
146 #[test]
147 fn test_examples() {
148 crate::test_examples(Encode)
149 }
150}