Unify closure serializing logic for to nuon, to msgpack, and to json (#15285)

# Description
Before this PR, `to msgpack`/`to msgpackz` and `to json` serialize
closures as `nil`/`null` respectively, when the `--serialize` option
isn't passed. This PR makes it an error to serialize closures to msgpack
or JSON without the `--serialize` flag, which is the behavior of `to
nuon`.

This PR also adds the `--serialize` flag to `to msgpack`.

This PR also changes `to nuon` and `to json` to return an error if they
cannot find the block contents of a closure, rather than serializing an
empty string or an error string, respectively. This behavior is
replicated for `to msgpack`.

It also changes `to nuon`'s error message for serializing closures
without `--serialize` to be the same as the new errors for `to json` and
`to msgpack`.

# User-Facing Changes

* Add `--serialize` flag to `to msgpack`, similar to the `--serialize`
flag for `to nuon` and `to json`.
* Serializing closures to JSON or msgpack without `--serialize`

Partially fixes #11738
This commit is contained in:
132ikl
2025-03-16 15:15:02 -04:00
committed by GitHub
parent 00e5e6d719
commit 83de8560ee
9 changed files with 136 additions and 69 deletions

View File

@@ -1,9 +0,0 @@
use crate::{BlockId, Value, VarId};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Closure {
pub block_id: BlockId,
pub captures: Vec<(VarId, Value)>,
}

View File

@@ -0,0 +1,35 @@
use std::borrow::Cow;
use crate::{engine::EngineState, BlockId, ShellError, Span, Value, VarId};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Closure {
pub block_id: BlockId,
pub captures: Vec<(VarId, Value)>,
}
impl Closure {
pub fn coerce_into_string<'a>(
&self,
engine_state: &'a EngineState,
span: Span,
) -> Result<Cow<'a, str>, ShellError> {
let block = engine_state.get_block(self.block_id);
if let Some(span) = block.span {
let contents_bytes = engine_state.get_span_contents(span);
Ok(String::from_utf8_lossy(contents_bytes))
} else {
Err(ShellError::CantConvert {
to_type: "string".into(),
from_type: "closure".into(),
span,
help: Some(format!(
"unable to retrieve block contents for closure with id {}",
self.block_id.get()
)),
})
}
}
}

View File

@@ -3,7 +3,7 @@ mod argument;
mod cached_file;
mod call;
mod call_info;
mod capture_block;
mod closure;
mod command;
mod description;
mod engine_state;
@@ -23,7 +23,7 @@ pub use cached_file::CachedFile;
pub use argument::*;
pub use call::*;
pub use call_info::*;
pub use capture_block::*;
pub use closure::*;
pub use command::*;
pub use engine_state::*;
pub use error_handler::*;