nu_plugin_protocol/plugin_custom_value/
mod.rs1use std::{cmp::Ordering, path::Path};
2
3use nu_protocol::{CustomValue, ShellError, Span, Spanned, Value, ast::Operator, casing::Casing};
4use nu_utils::SharedCow;
5
6use serde::{Deserialize, Serialize};
7
8#[cfg(test)]
9mod tests;
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
27pub struct PluginCustomValue(SharedCow<SharedContent>);
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
31struct SharedContent {
32 name: String,
34 data: Vec<u8>,
36 #[serde(default, skip_serializing_if = "is_false")]
40 notify_on_drop: bool,
41}
42
43fn is_false(b: &bool) -> bool {
44 !b
45}
46
47#[typetag::serde]
48impl CustomValue for PluginCustomValue {
49 fn clone_value(&self, span: Span) -> Value {
50 self.clone().into_value(span)
51 }
52
53 fn type_name(&self) -> String {
54 self.name().to_owned()
55 }
56
57 fn to_base_value(&self, _span: Span) -> Result<Value, ShellError> {
58 panic!("to_base_value() not available on plugin custom value without source");
59 }
60
61 fn follow_path_int(
62 &self,
63 _self_span: Span,
64 _index: usize,
65 _path_span: Span,
66 _optional: bool,
67 ) -> Result<Value, ShellError> {
68 panic!("follow_path_int() not available on plugin custom value without source");
69 }
70
71 fn follow_path_string(
72 &self,
73 _self_span: Span,
74 _column_name: String,
75 _path_span: Span,
76 _optional: bool,
77 _casing: Casing,
78 ) -> Result<Value, ShellError> {
79 panic!("follow_path_string() not available on plugin custom value without source");
80 }
81
82 fn partial_cmp(&self, _other: &Value) -> Option<Ordering> {
83 panic!("partial_cmp() not available on plugin custom value without source");
84 }
85
86 fn operation(
87 &self,
88 _lhs_span: Span,
89 _operator: Operator,
90 _op_span: Span,
91 _right: &Value,
92 ) -> Result<Value, ShellError> {
93 panic!("operation() not available on plugin custom value without source");
94 }
95
96 fn save(
97 &self,
98 _path: Spanned<&Path>,
99 _value_span: Span,
100 _save_span: Span,
101 ) -> Result<(), ShellError> {
102 panic!("save() not available on plugin custom value without source");
103 }
104
105 fn as_any(&self) -> &dyn std::any::Any {
106 self
107 }
108
109 fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
110 self
111 }
112}
113
114impl PluginCustomValue {
115 pub fn new(name: String, data: Vec<u8>, notify_on_drop: bool) -> PluginCustomValue {
117 PluginCustomValue(SharedCow::new(SharedContent {
118 name,
119 data,
120 notify_on_drop,
121 }))
122 }
123
124 pub fn into_value(self, span: Span) -> Value {
126 Value::custom(Box::new(self), span)
127 }
128
129 pub fn name(&self) -> &str {
131 &self.0.name
132 }
133
134 pub fn data(&self) -> &[u8] {
136 &self.0.data
137 }
138
139 pub fn notify_on_drop(&self) -> bool {
141 self.0.notify_on_drop
142 }
143
144 pub fn ref_count(&self) -> usize {
146 SharedCow::ref_count(&self.0)
147 }
148
149 pub fn serialize_from_custom_value(
152 custom_value: &dyn CustomValue,
153 span: Span,
154 ) -> Result<PluginCustomValue, ShellError> {
155 let name = custom_value.type_name();
156 let notify_on_drop = custom_value.notify_plugin_on_drop();
157 rmp_serde::to_vec(custom_value)
158 .map(|data| PluginCustomValue::new(name, data, notify_on_drop))
159 .map_err(|err| ShellError::CustomValueFailedToEncode {
160 msg: err.to_string(),
161 span,
162 })
163 }
164
165 pub fn deserialize_to_custom_value(
168 &self,
169 span: Span,
170 ) -> Result<Box<dyn CustomValue>, ShellError> {
171 rmp_serde::from_slice::<Box<dyn CustomValue>>(self.data()).map_err(|err| {
172 ShellError::CustomValueFailedToDecode {
173 msg: err.to_string(),
174 span,
175 }
176 })
177 }
178 pub fn serialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
181 value.recurse_mut(&mut |value| {
182 let span = value.span();
183 match value {
184 Value::Custom { val, .. } => {
185 if val.as_any().downcast_ref::<PluginCustomValue>().is_some() {
186 Ok(())
188 } else {
189 let serialized = Self::serialize_from_custom_value(&**val, span)?;
190 *value = Value::custom(Box::new(serialized), span);
191 Ok(())
192 }
193 }
194 _ => Ok(()),
195 }
196 })
197 }
198
199 pub fn deserialize_custom_values_in(value: &mut Value) -> Result<(), ShellError> {
202 value.recurse_mut(&mut |value| {
203 let span = value.span();
204 match value {
205 Value::Custom { val, .. } => {
206 if let Some(val) = val.as_any().downcast_ref::<PluginCustomValue>() {
207 let deserialized = val.deserialize_to_custom_value(span)?;
208 *value = Value::custom(deserialized, span);
209 Ok(())
210 } else {
211 Ok(())
213 }
214 }
215 _ => Ok(()),
216 }
217 })
218 }
219
220 pub fn render_to_base_value_in(value: &mut Value) -> Result<(), ShellError> {
222 value.recurse_mut(&mut |value| {
223 let span = value.span();
224 match value {
225 Value::Custom { val, .. } => {
226 *value = val.to_base_value(span)?;
227 Ok(())
228 }
229 _ => Ok(()),
230 }
231 })
232 }
233}