nu_plugin_core/serializers/
mod.rs

1use nu_plugin_protocol::{PluginInput, PluginOutput};
2use nu_protocol::ShellError;
3
4pub mod json;
5pub mod msgpack;
6
7#[cfg(test)]
8mod tests;
9
10/// Encoder for a specific message type. Usually implemented on [`PluginInput`]
11/// and [`PluginOutput`].
12pub trait Encoder<T>: Clone + Send + Sync {
13    /// Serialize a value in the [`PluginEncoder`]s format
14    ///
15    /// Returns [`ShellError::Io`] if there was a problem writing, or
16    /// [`ShellError::PluginFailedToEncode`] for a serialization error.
17    fn encode(&self, data: &T, writer: &mut impl std::io::Write) -> Result<(), ShellError>;
18
19    /// Deserialize a value from the [`PluginEncoder`]'s format
20    ///
21    /// Returns `None` if there is no more output to receive.
22    ///
23    /// Returns [`ShellError::Io`] if there was a problem reading, or
24    /// [`ShellError::PluginFailedToDecode`] for a deserialization error.
25    fn decode(&self, reader: &mut impl std::io::BufRead) -> Result<Option<T>, ShellError>;
26}
27
28/// Encoding scheme that defines a plugin's communication protocol with Nu
29pub trait PluginEncoder: Encoder<PluginInput> + Encoder<PluginOutput> {
30    /// The name of the encoder (e.g., `json`)
31    fn name(&self) -> &str;
32}
33
34/// Enum that supports all of the plugin serialization formats.
35#[derive(Clone, Copy, Debug)]
36pub enum EncodingType {
37    Json(json::JsonSerializer),
38    MsgPack(msgpack::MsgPackSerializer),
39}
40
41impl EncodingType {
42    /// Determine the plugin encoding type from the provided byte string (either `b"json"` or
43    /// `b"msgpack"`).
44    pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
45        match bytes {
46            b"json" => Some(Self::Json(json::JsonSerializer {})),
47            b"msgpack" => Some(Self::MsgPack(msgpack::MsgPackSerializer {})),
48            _ => None,
49        }
50    }
51}
52
53impl<T> Encoder<T> for EncodingType
54where
55    json::JsonSerializer: Encoder<T>,
56    msgpack::MsgPackSerializer: Encoder<T>,
57{
58    fn encode(&self, data: &T, writer: &mut impl std::io::Write) -> Result<(), ShellError> {
59        match self {
60            EncodingType::Json(encoder) => encoder.encode(data, writer),
61            EncodingType::MsgPack(encoder) => encoder.encode(data, writer),
62        }
63    }
64
65    fn decode(&self, reader: &mut impl std::io::BufRead) -> Result<Option<T>, ShellError> {
66        match self {
67            EncodingType::Json(encoder) => encoder.decode(reader),
68            EncodingType::MsgPack(encoder) => encoder.decode(reader),
69        }
70    }
71}