1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
use std::{cmp::Ordering, fmt, path::Path};
use crate::shell_error::generic::GenericError;
use crate::{ShellError, Span, Spanned, Type, Value, ast::Operator, casing::Casing};
/// Trait definition for a custom [`Value`](crate::Value) type
#[typetag::serde(tag = "type")]
pub trait CustomValue: fmt::Debug + Send + Sync {
/// Custom `Clone` implementation
///
/// This can reemit a `Value::Custom(Self, span)` or materialize another representation
/// if necessary.
fn clone_value(&self, span: Span) -> Value;
//fn category(&self) -> Category;
/// The friendly type name to show for the custom value, e.g. in `describe` and in error
/// messages. This does not have to be the same as the name of the struct or enum, but
/// conventionally often is.
fn type_name(&self) -> String;
/// Converts the custom value to a base nushell value.
///
/// This imposes the requirement that you can represent the custom value in some form using the
/// Value representations that already exist in nushell
fn to_base_value(&self, span: Span) -> Result<Value, ShellError>;
/// Any representation used to downcast object to its original type
fn as_any(&self) -> &dyn std::any::Any;
/// Any representation used to downcast object to its original type (mutable reference)
fn as_mut_any(&mut self) -> &mut dyn std::any::Any;
/// Follow cell path by numeric index (e.g. rows).
///
/// Let `$val` be the custom value then these are the fields passed to this method:
/// ```text
/// ╭── index [path_span]
/// ┴
/// $val.0?
/// ──┬─ ┬
/// │ ╰── optional, `true` if present
/// ╰── self [self_span]
/// ```
fn follow_path_int(
&self,
self_span: Span,
index: usize,
path_span: Span,
optional: bool,
) -> Result<Value, ShellError> {
let _ = (self_span, index, optional);
Err(ShellError::IncompatiblePathAccess {
type_name: self.type_name(),
span: path_span,
})
}
/// Follow cell path by string key (e.g. columns).
///
/// Let `$val` be the custom value then these are the fields passed to this method:
/// ```text
/// ╭── column_name [path_span]
/// │ ╭── casing, `Casing::Insensitive` if present
/// ───┴── ┴
/// $val.column?!
/// ──┬─ ┬
/// │ ╰── optional, `true` if present
/// ╰── self [self_span]
/// ```
fn follow_path_string(
&self,
self_span: Span,
column_name: String,
path_span: Span,
optional: bool,
casing: Casing,
) -> Result<Value, ShellError> {
let _ = (self_span, column_name, optional, casing);
Err(ShellError::IncompatiblePathAccess {
type_name: self.type_name(),
span: path_span,
})
}
/// ordering with other value (see [`std::cmp::PartialOrd`])
fn partial_cmp(&self, _other: &Value) -> Option<Ordering> {
None
}
/// Definition of an operation between the object that implements the trait
/// and another Value.
///
/// The Operator enum is used to indicate the expected operation.
///
/// Default impl raises [`ShellError::OperatorUnsupportedType`].
fn operation(
&self,
lhs_span: Span,
operator: Operator,
op: Span,
right: &Value,
) -> Result<Value, ShellError> {
let _ = (lhs_span, right);
Err(ShellError::OperatorUnsupportedType {
op: operator,
unsupported: Type::Custom(self.type_name().into()),
op_span: op,
unsupported_span: lhs_span,
help: None,
})
}
/// Save custom value to disk.
///
/// This method is used in `save` to save a custom value to disk.
/// This is done before opening any file, so saving can be handled differently.
///
/// The default impl just returns an error.
fn save(
&self,
path: Spanned<&Path>,
value_span: Span,
save_span: Span,
) -> Result<(), ShellError> {
let _ = path;
Err(ShellError::Generic(
GenericError::new(
"Cannot save custom value",
format!("Saving custom value {} failed", self.type_name()),
save_span,
)
.with_inner([ShellError::Generic(
GenericError::new(
"Custom value does not implement `save`",
format!("{} doesn't implement saving to disk", self.type_name()),
value_span,
)
.with_help("Check the plugin's documentation for this value type. It might use a different way to save."),
)]),
))
}
/// For custom values in plugins: return `true` here if you would like to be notified when all
/// copies of this custom value are dropped in the engine.
///
/// The notification will take place via `custom_value_dropped()` on the plugin type.
///
/// The default is `false`.
fn notify_plugin_on_drop(&self) -> bool {
false
}
/// Returns an estimate of the memory size used by this CustomValue in bytes
///
/// The default implementation returns the size of the trait object.
fn memory_size(&self) -> usize {
std::mem::size_of_val(self)
}
/// Returns `true` if this custom value should be iterable (like a list) when used with
/// commands like `each`, `where`, etc.
///
/// When this returns `true`, the engine will call `to_base_value()` to convert the custom
/// value to a list before iteration. This is useful for lazy data structures like database
/// query builders that should behave like lists when iterated.
///
/// The default is `false`.
#[deprecated(
since = "0.111.1",
note = "will be replaced by a new custom-value iterator system next release; \
avoid new uses unless you need current behavior"
)]
fn is_iterable(&self) -> bool {
false
}
}