1use crate::{Range, Record, ShellError, Span, Value, ast::CellPath, engine::Closure};
2use chrono::{DateTime, FixedOffset};
3use nu_path::form::PathForm;
4use std::{
5 borrow::{Borrow, Cow},
6 collections::HashMap,
7};
8
9pub trait IntoValue: Sized {
95 fn into_value(self, span: Span) -> Value;
97}
98
99impl<T, const N: usize> IntoValue for [T; N]
102where
103 T: IntoValue,
104{
105 fn into_value(self, span: Span) -> Value {
106 Vec::from(self).into_value(span)
107 }
108}
109
110macro_rules! primitive_into_value {
111 ($type:ty, $method:ident) => {
112 primitive_into_value!($type => $type, $method);
113 };
114
115 ($type:ty => $as_type:ty, $method:ident) => {
116 impl IntoValue for $type {
117 fn into_value(self, span: Span) -> Value {
118 Value::$method(<$as_type>::from(self), span)
119 }
120 }
121 };
122}
123
124primitive_into_value!(bool, bool);
125primitive_into_value!(char, string);
126primitive_into_value!(f32 => f64, float);
127primitive_into_value!(f64, float);
128primitive_into_value!(i8 => i64, int);
129primitive_into_value!(i16 => i64, int);
130primitive_into_value!(i32 => i64, int);
131primitive_into_value!(i64, int);
132primitive_into_value!(u8 => i64, int);
133primitive_into_value!(u16 => i64, int);
134primitive_into_value!(u32 => i64, int);
135impl IntoValue for isize {
138 fn into_value(self, span: Span) -> Value {
139 Value::int(self as i64, span)
140 }
141}
142
143impl IntoValue for () {
144 fn into_value(self, span: Span) -> Value {
145 Value::nothing(span)
146 }
147}
148
149macro_rules! tuple_into_value {
150 ($($t:ident:$n:tt),+) => {
151 impl<$($t),+> IntoValue for ($($t,)+) where $($t: IntoValue,)+ {
152 fn into_value(self, span: Span) -> Value {
153 let vals = vec![$(self.$n.into_value(span)),+];
154 Value::list(vals, span)
155 }
156 }
157 }
158}
159
160tuple_into_value!(T0:0);
162tuple_into_value!(T0:0, T1:1);
163tuple_into_value!(T0:0, T1:1, T2:2);
164tuple_into_value!(T0:0, T1:1, T2:2, T3:3);
165tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4);
166tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
167tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
168tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
169tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
170tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
171tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10);
172tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10, T11:11);
173
174impl IntoValue for String {
177 fn into_value(self, span: Span) -> Value {
178 Value::string(self, span)
179 }
180}
181
182impl IntoValue for &str {
183 fn into_value(self, span: Span) -> Value {
184 Value::string(self, span)
185 }
186}
187
188impl<T> IntoValue for Vec<T>
189where
190 T: IntoValue,
191{
192 fn into_value(self, span: Span) -> Value {
193 Value::list(self.into_iter().map(|v| v.into_value(span)).collect(), span)
194 }
195}
196
197impl<T> IntoValue for Box<T>
198where
199 T: IntoValue,
200{
201 fn into_value(self, span: Span) -> Value {
202 let t: T = *self;
203 t.into_value(span)
204 }
205}
206
207impl<T> IntoValue for Option<T>
208where
209 T: IntoValue,
210{
211 fn into_value(self, span: Span) -> Value {
212 match self {
213 Some(v) => v.into_value(span),
214 None => Value::nothing(span),
215 }
216 }
217}
218
219impl<B> IntoValue for Cow<'_, B>
225where
226 B: ?Sized + ToOwned,
227 B::Owned: IntoValue,
228{
229 fn into_value(self, span: Span) -> Value {
230 <B::Owned as IntoValue>::into_value(self.into_owned(), span)
231 }
232}
233
234impl<K, V> IntoValue for HashMap<K, V>
235where
236 K: Borrow<str> + Into<String>,
237 V: IntoValue,
238{
239 fn into_value(self, span: Span) -> Value {
240 self.into_iter()
249 .map(|(k, v)| (k.into(), v.into_value(span)))
250 .collect::<Record>()
251 .into_value(span)
252 }
253}
254
255impl IntoValue for std::time::Duration {
256 fn into_value(self, span: Span) -> Value {
257 let val: u128 = self.as_nanos();
258 debug_assert!(val <= i64::MAX as u128, "duration value too large");
259 let val: i64 = val.try_into().unwrap_or(i64::MAX);
261 Value::duration(val, span)
262 }
263}
264
265impl IntoValue for &std::path::Path {
266 fn into_value(self, span: Span) -> Value {
267 Value::string(self.to_string_lossy(), span)
268 }
269}
270
271impl IntoValue for std::path::PathBuf {
272 fn into_value(self, span: Span) -> Value {
273 Value::string(self.to_string_lossy(), span)
274 }
275}
276
277impl IntoValue for Range {
280 fn into_value(self, span: Span) -> Value {
281 Value::range(self, span)
282 }
283}
284
285impl IntoValue for Record {
286 fn into_value(self, span: Span) -> Value {
287 Value::record(self, span)
288 }
289}
290
291impl IntoValue for Closure {
292 fn into_value(self, span: Span) -> Value {
293 Value::closure(self, span)
294 }
295}
296
297impl IntoValue for ShellError {
298 fn into_value(self, span: Span) -> Value {
299 Value::error(self, span)
300 }
301}
302
303impl IntoValue for CellPath {
304 fn into_value(self, span: Span) -> Value {
305 Value::cell_path(self, span)
306 }
307}
308
309impl IntoValue for Value {
310 fn into_value(self, span: Span) -> Value {
311 self.with_span(span)
312 }
313}
314
315impl<Form: PathForm> IntoValue for &nu_path::Path<Form> {
316 fn into_value(self, span: Span) -> Value {
317 Value::string(self.to_string_lossy(), span)
318 }
319}
320
321impl<Form: PathForm> IntoValue for nu_path::PathBuf<Form> {
322 fn into_value(self, span: Span) -> Value {
323 Value::string(self.to_string_lossy(), span)
324 }
325}
326
327impl IntoValue for DateTime<FixedOffset> {
330 fn into_value(self, span: Span) -> Value {
331 Value::date(self, span)
332 }
333}
334
335impl IntoValue for bytes::Bytes {
336 fn into_value(self, span: Span) -> Value {
337 Value::binary(self.to_vec(), span)
338 }
339}
340
341impl IntoValue for serde_json::Value {
342 fn into_value(self, span: Span) -> Value {
343 match self {
344 serde_json::Value::Null => Value::nothing(span),
345 serde_json::Value::Bool(b) => Value::bool(b, span),
346 serde_json::Value::Number(num) => {
347 if let Some(n) = num.as_i64() {
348 return Value::int(n, span);
349 }
350 Value::float(
351 num.as_f64()
352 .expect("should always return some floating point number"),
353 span,
354 )
355 }
356 serde_json::Value::String(s) => Value::string(s, span),
357 serde_json::Value::Array(values) => Value::list(
358 values.into_iter().map(|v| v.into_value(span)).collect(),
359 span,
360 ),
361 serde_json::Value::Object(map) => Value::record(
362 Record::from_iter(map.into_iter().map(|(k, v)| (k, v.into_value(span)))),
363 span,
364 ),
365 }
366 }
367}
368
369pub trait TryIntoValue: Sized {
378 fn try_into_value(self, span: Span) -> Result<Value, ShellError>;
381}
382
383impl<T> TryIntoValue for T
384where
385 T: IntoValue,
386{
387 fn try_into_value(self, span: Span) -> Result<Value, ShellError> {
388 Ok(self.into_value(span))
389 }
390}