nu_plugin_core/serializers/
msgpack.rs1use std::io::ErrorKind;
2
3use nu_plugin_protocol::{PluginInput, PluginOutput};
4use nu_protocol::{shell_error::io::IoError, ShellError};
5use serde::Deserialize;
6
7use crate::{Encoder, PluginEncoder};
8
9#[derive(Clone, Copy, Debug)]
14pub struct MsgPackSerializer;
15
16impl PluginEncoder for MsgPackSerializer {
17 fn name(&self) -> &str {
18 "msgpack"
19 }
20}
21
22impl Encoder<PluginInput> for MsgPackSerializer {
23 fn encode(
24 &self,
25 plugin_input: &PluginInput,
26 writer: &mut impl std::io::Write,
27 ) -> Result<(), nu_protocol::ShellError> {
28 rmp_serde::encode::write_named(writer, plugin_input).map_err(rmp_encode_err)
29 }
30
31 fn decode(
32 &self,
33 reader: &mut impl std::io::BufRead,
34 ) -> Result<Option<PluginInput>, ShellError> {
35 let mut de = rmp_serde::Deserializer::new(reader);
36 PluginInput::deserialize(&mut de)
37 .map(Some)
38 .or_else(rmp_decode_err)
39 }
40}
41
42impl Encoder<PluginOutput> for MsgPackSerializer {
43 fn encode(
44 &self,
45 plugin_output: &PluginOutput,
46 writer: &mut impl std::io::Write,
47 ) -> Result<(), ShellError> {
48 rmp_serde::encode::write_named(writer, plugin_output).map_err(rmp_encode_err)
49 }
50
51 fn decode(
52 &self,
53 reader: &mut impl std::io::BufRead,
54 ) -> Result<Option<PluginOutput>, ShellError> {
55 let mut de = rmp_serde::Deserializer::new(reader);
56 PluginOutput::deserialize(&mut de)
57 .map(Some)
58 .or_else(rmp_decode_err)
59 }
60}
61
62fn rmp_encode_err(err: rmp_serde::encode::Error) -> ShellError {
64 match err {
65 rmp_serde::encode::Error::InvalidValueWrite(_) => {
66 ShellError::Io(IoError::new_internal(
68 std::io::ErrorKind::Other,
70 "Could not encode with rmp",
71 nu_protocol::location!(),
72 ))
73 }
74 _ => {
75 ShellError::PluginFailedToEncode {
77 msg: err.to_string(),
78 }
79 }
80 }
81}
82
83fn rmp_decode_err<T>(err: rmp_serde::decode::Error) -> Result<Option<T>, ShellError> {
85 match err {
86 rmp_serde::decode::Error::InvalidMarkerRead(err)
87 | rmp_serde::decode::Error::InvalidDataRead(err) => {
88 if matches!(err.kind(), ErrorKind::UnexpectedEof) {
89 Ok(None)
91 } else {
92 Err(ShellError::Io(IoError::new_internal(
94 std::io::ErrorKind::Other,
96 "Could not decode with rmp",
97 nu_protocol::location!(),
98 )))
99 }
100 }
101 _ => {
102 Err(ShellError::PluginFailedToDecode {
104 msg: err.to_string(),
105 })
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 crate::serializers::tests::generate_tests!(MsgPackSerializer {});
114}