Remove serde derive for ShellError, replace via LabeledError (#12319)

# Description

This changes the interface for plugins to always represent errors as
`LabeledError`s. This is good for altlang plugins, as it would suck for
them to have to implement and track `ShellError`. We save a lot of
generated code from the `ShellError` serde impl too, so `nu` and plugins
get to have a smaller binary size.

Reduces the release binary size by 1.2 MiB on my build configuration.

# User-Facing Changes

- Changes plugin protocol. `ShellError` no longer serialized.
- `ShellError` serialize output is different
- `ShellError` no longer deserializes to exactly the same value as
serialized

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

- [ ] Document in plugin protocol reference
This commit is contained in:
Devyn Cairns
2024-03-30 06:21:40 -07:00
committed by GitHub
parent cc39069e13
commit 714a0ccd24
4 changed files with 101 additions and 10 deletions

View File

@ -103,7 +103,8 @@ fn list_reader_recv_wrong_type() -> Result<(), ShellError> {
#[test]
fn reader_recv_raw_messages() -> Result<(), ShellError> {
let (tx, rx) = mpsc::channel();
let mut reader = StreamReader::new(0, rx, TestSink::default());
let mut reader =
StreamReader::<Result<Vec<u8>, ShellError>, _>::new(0, rx, TestSink::default());
tx.send(Ok(Some(StreamData::Raw(Ok(vec![10, 20])))))
.unwrap();
@ -458,7 +459,7 @@ fn stream_manager_write_scenario() -> Result<(), ShellError> {
let expected_values = vec![b"hello".to_vec(), b"world".to_vec(), b"test".to_vec()];
for value in &expected_values {
writable.write(Ok(value.clone()))?;
writable.write(Ok::<_, ShellError>(value.clone()))?;
}
// Now try signalling ack

View File

@ -184,8 +184,14 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> {
test.add(StreamMessage::Data(14, Value::test_int(1).into()));
for _ in 0..iterations {
test.add(StreamMessage::Data(12, Ok(out_pattern.clone()).into()));
test.add(StreamMessage::Data(13, Ok(err_pattern.clone()).into()));
test.add(StreamMessage::Data(
12,
StreamData::Raw(Ok(out_pattern.clone())),
));
test.add(StreamMessage::Data(
13,
StreamData::Raw(Ok(err_pattern.clone())),
));
}
test.add(StreamMessage::End(12));
test.add(StreamMessage::End(13));

View File

@ -236,7 +236,7 @@ impl From<StreamMessage> for PluginInput {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum StreamData {
List(Value),
Raw(Result<Vec<u8>, ShellError>),
Raw(Result<Vec<u8>, LabeledError>),
}
impl From<Value> for StreamData {
@ -245,9 +245,15 @@ impl From<Value> for StreamData {
}
}
impl From<Result<Vec<u8>, LabeledError>> for StreamData {
fn from(value: Result<Vec<u8>, LabeledError>) -> Self {
StreamData::Raw(value)
}
}
impl From<Result<Vec<u8>, ShellError>> for StreamData {
fn from(value: Result<Vec<u8>, ShellError>) -> Self {
StreamData::Raw(value)
value.map_err(LabeledError::from).into()
}
}
@ -264,10 +270,10 @@ impl TryFrom<StreamData> for Value {
}
}
impl TryFrom<StreamData> for Result<Vec<u8>, ShellError> {
impl TryFrom<StreamData> for Result<Vec<u8>, LabeledError> {
type Error = ShellError;
fn try_from(data: StreamData) -> Result<Result<Vec<u8>, ShellError>, ShellError> {
fn try_from(data: StreamData) -> Result<Result<Vec<u8>, LabeledError>, ShellError> {
match data {
StreamData::Raw(value) => Ok(value),
StreamData::List(_) => Err(ShellError::PluginFailedToDecode {
@ -277,6 +283,14 @@ impl TryFrom<StreamData> for Result<Vec<u8>, ShellError> {
}
}
impl TryFrom<StreamData> for Result<Vec<u8>, ShellError> {
type Error = ShellError;
fn try_from(value: StreamData) -> Result<Result<Vec<u8>, ShellError>, ShellError> {
Result::<Vec<u8>, LabeledError>::try_from(value).map(|res| res.map_err(ShellError::from))
}
}
/// A stream control or data message.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum StreamMessage {