nu_protocol/engine/
closure.rs1use std::{
2 borrow::Cow,
3 fmt::{self, Debug},
4};
5
6use crate::{BlockId, ShellError, Span, Value, VarId, engine::EngineState};
7
8use serde::{Deserialize, Serialize};
9
10#[derive(Clone, Serialize, Deserialize)]
11pub struct Closure {
12 pub block_id: BlockId,
13 pub captures: Vec<(VarId, Value)>,
14}
15
16impl Debug for Closure {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("Closure")
19 .field("block_id", &self.block_id)
20 .field(
21 "captures",
22 &fmt::from_fn(|f| {
23 f.debug_map()
24 .entries(self.captures.iter().map(|(k, v)| (k, v)))
25 .finish()
26 }),
27 )
28 .finish()
29 }
30}
31
32impl Closure {
33 pub fn coerce_into_string<'a>(
34 &self,
35 engine_state: &'a EngineState,
36 span: Span,
37 ) -> Result<Cow<'a, str>, ShellError> {
38 let block = engine_state.get_block(self.block_id);
39 if let Some(span) = block.span {
40 let contents_bytes = engine_state.get_span_contents(span);
41 Ok(String::from_utf8_lossy(contents_bytes))
42 } else {
43 Err(ShellError::CantConvert {
44 to_type: "string".into(),
45 from_type: "closure".into(),
46 span,
47 help: Some(format!(
48 "unable to retrieve block contents for closure with id {}",
49 self.block_id.get()
50 )),
51 })
52 }
53 }
54
55 pub fn memory_size(&self) -> usize {
57 std::mem::size_of::<Self>()
58 + self
59 .captures
60 .iter()
61 .map(|(_, v)| v.memory_size())
62 .sum::<usize>()
63 }
64
65 pub(crate) fn compact_debug(&self) -> impl Debug {
66 fmt::from_fn(|f| {
67 write!(f, "{:?}: ", self.block_id)?;
68 f.debug_map()
69 .entries(self.captures.iter().map(|(k, v)| (k, v)))
70 .finish()
71 })
72 }
73}