nu_command/formats/to/
msgpackz.rs1use std::io::Write;
2
3use nu_engine::command_prelude::*;
4use nu_protocol::shell_error::io::IoError;
5
6use super::msgpack::write_value;
7
8const BUFFER_SIZE: usize = 65536;
9const DEFAULT_QUALITY: u32 = 3; const DEFAULT_WINDOW_SIZE: u32 = 20;
11
12#[derive(Clone)]
13pub struct ToMsgpackz;
14
15impl Command for ToMsgpackz {
16 fn name(&self) -> &str {
17 "to msgpackz"
18 }
19
20 fn signature(&self) -> Signature {
21 Signature::build(self.name())
22 .input_output_type(Type::Any, Type::Binary)
23 .named(
24 "quality",
25 SyntaxShape::Int,
26 "Quality of brotli compression (default 3)",
27 Some('q'),
28 )
29 .named(
30 "window-size",
31 SyntaxShape::Int,
32 "Window size for brotli compression (default 20)",
33 Some('w'),
34 )
35 .switch(
36 "serialize",
37 "serialize nushell types that cannot be deserialized",
38 Some('s'),
39 )
40 .category(Category::Formats)
41 }
42
43 fn description(&self) -> &str {
44 "Convert Nu values into brotli-compressed MessagePack."
45 }
46
47 fn extra_description(&self) -> &str {
48 "This is the format used by the plugin registry file ($nu.plugin-path)."
49 }
50
51 fn run(
52 &self,
53 engine_state: &EngineState,
54 stack: &mut Stack,
55 call: &Call,
56 input: PipelineData,
57 ) -> Result<PipelineData, ShellError> {
58 fn to_u32(n: Spanned<i64>) -> Result<Spanned<u32>, ShellError> {
59 u32::try_from(n.item)
60 .map_err(|err| ShellError::CantConvert {
61 to_type: "u32".into(),
62 from_type: "int".into(),
63 span: n.span,
64 help: Some(err.to_string()),
65 })
66 .map(|o| o.into_spanned(n.span))
67 }
68
69 let quality = call
70 .get_flag(engine_state, stack, "quality")?
71 .map(to_u32)
72 .transpose()?;
73 let window_size = call
74 .get_flag(engine_state, stack, "window-size")?
75 .map(to_u32)
76 .transpose()?;
77 let serialize_types = call.has_flag(engine_state, stack, "serialize")?;
78
79 let value_span = input.span().unwrap_or(call.head);
80 let value = input.into_value(value_span)?;
81 let mut out_buf = vec![];
82 let mut out = brotli::CompressorWriter::new(
83 &mut out_buf,
84 BUFFER_SIZE,
85 quality.map(|q| q.item).unwrap_or(DEFAULT_QUALITY),
86 window_size.map(|w| w.item).unwrap_or(DEFAULT_WINDOW_SIZE),
87 );
88
89 write_value(
90 &mut out,
91 &value,
92 0,
93 engine_state,
94 call.head,
95 serialize_types,
96 )?;
97 out.flush()
98 .map_err(|err| IoError::new(err, call.head, None))?;
99 drop(out);
100
101 Ok(Value::binary(out_buf, call.head).into_pipeline_data())
102 }
103}