mirror of
https://github.com/nushell/nushell.git
synced 2025-05-01 08:34:26 +02:00
# Description This breaks `nu-plugin` up into four crates: - `nu-plugin-protocol`: just the type definitions for the protocol, no I/O. If someone wanted to wire up something more bare metal, maybe for async I/O, they could use this. - `nu-plugin-core`: the shared stuff between engine/plugin. Less stable interface. - `nu-plugin-engine`: everything required for the engine to talk to plugins. Less stable interface. - `nu-plugin`: everything required for the plugin to talk to the engine, what plugin developers use. Should be the most stable interface. No changes are made to the interface exposed by `nu-plugin` - it should all still be there. Re-exports from `nu-plugin-protocol` or `nu-plugin-core` are used as required. Plugins shouldn't ever have to use those crates directly. This should be somewhat faster to compile as `nu-plugin-engine` and `nu-plugin` can compile in parallel, and the engine doesn't need `nu-plugin` and plugins don't need `nu-plugin-engine` (except for test support), so that should reduce what needs to be compiled too. The only significant change here other than splitting stuff up was to break the `source` out of `PluginCustomValue` and create a new `PluginCustomValueWithSource` type that contains that instead. One bonus of that is we get rid of the option and it's now more type-safe, but it also means that the logic for that stuff (actually running the plugin for custom value ops) can live entirely within the `nu-plugin-engine` crate. # User-Facing Changes - New crates. - Added `local-socket` feature for `nu` to try to make it possible to compile without that support if needed. # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib`
72 lines
2.4 KiB
Rust
72 lines
2.4 KiB
Rust
use nu_plugin_protocol::{PluginInput, PluginOutput};
|
|
use nu_protocol::ShellError;
|
|
|
|
pub mod json;
|
|
pub mod msgpack;
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
/// Encoder for a specific message type. Usually implemented on [`PluginInput`]
|
|
/// and [`PluginOutput`].
|
|
pub trait Encoder<T>: Clone + Send + Sync {
|
|
/// Serialize a value in the [`PluginEncoder`]s format
|
|
///
|
|
/// Returns [`ShellError::IOError`] if there was a problem writing, or
|
|
/// [`ShellError::PluginFailedToEncode`] for a serialization error.
|
|
fn encode(&self, data: &T, writer: &mut impl std::io::Write) -> Result<(), ShellError>;
|
|
|
|
/// Deserialize a value from the [`PluginEncoder`]'s format
|
|
///
|
|
/// Returns `None` if there is no more output to receive.
|
|
///
|
|
/// Returns [`ShellError::IOError`] if there was a problem reading, or
|
|
/// [`ShellError::PluginFailedToDecode`] for a deserialization error.
|
|
fn decode(&self, reader: &mut impl std::io::BufRead) -> Result<Option<T>, ShellError>;
|
|
}
|
|
|
|
/// Encoding scheme that defines a plugin's communication protocol with Nu
|
|
pub trait PluginEncoder: Encoder<PluginInput> + Encoder<PluginOutput> {
|
|
/// The name of the encoder (e.g., `json`)
|
|
fn name(&self) -> &str;
|
|
}
|
|
|
|
/// Enum that supports all of the plugin serialization formats.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum EncodingType {
|
|
Json(json::JsonSerializer),
|
|
MsgPack(msgpack::MsgPackSerializer),
|
|
}
|
|
|
|
impl EncodingType {
|
|
/// Determine the plugin encoding type from the provided byte string (either `b"json"` or
|
|
/// `b"msgpack"`).
|
|
pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
|
|
match bytes {
|
|
b"json" => Some(Self::Json(json::JsonSerializer {})),
|
|
b"msgpack" => Some(Self::MsgPack(msgpack::MsgPackSerializer {})),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> Encoder<T> for EncodingType
|
|
where
|
|
json::JsonSerializer: Encoder<T>,
|
|
msgpack::MsgPackSerializer: Encoder<T>,
|
|
{
|
|
fn encode(&self, data: &T, writer: &mut impl std::io::Write) -> Result<(), ShellError> {
|
|
match self {
|
|
EncodingType::Json(encoder) => encoder.encode(data, writer),
|
|
EncodingType::MsgPack(encoder) => encoder.encode(data, writer),
|
|
}
|
|
}
|
|
|
|
fn decode(&self, reader: &mut impl std::io::BufRead) -> Result<Option<T>, ShellError> {
|
|
match self {
|
|
EncodingType::Json(encoder) => encoder.decode(reader),
|
|
EncodingType::MsgPack(encoder) => encoder.decode(reader),
|
|
}
|
|
}
|
|
}
|