use std::collections::HashMap;
use crate::{Record, ShellError, Span, Value};
pub trait IntoValue: Sized {
fn into_value(self, span: Span) -> Value;
}
impl<T, const N: usize> IntoValue for [T; N]
where
T: IntoValue,
{
fn into_value(self, span: Span) -> Value {
Vec::from(self).into_value(span)
}
}
macro_rules! primitive_into_value {
($type:ty, $method:ident) => {
primitive_into_value!($type => $type, $method);
};
($type:ty => $as_type:ty, $method:ident) => {
impl IntoValue for $type {
fn into_value(self, span: Span) -> Value {
Value::$method(<$as_type>::from(self), span)
}
}
};
}
primitive_into_value!(bool, bool);
primitive_into_value!(char, string);
primitive_into_value!(f32 => f64, float);
primitive_into_value!(f64, float);
primitive_into_value!(i8 => i64, int);
primitive_into_value!(i16 => i64, int);
primitive_into_value!(i32 => i64, int);
primitive_into_value!(i64, int);
primitive_into_value!(u8 => i64, int);
primitive_into_value!(u16 => i64, int);
primitive_into_value!(u32 => i64, int);
impl IntoValue for isize {
fn into_value(self, span: Span) -> Value {
Value::int(self as i64, span)
}
}
impl IntoValue for () {
fn into_value(self, span: Span) -> Value {
Value::nothing(span)
}
}
macro_rules! tuple_into_value {
($($t:ident:$n:tt),+) => {
impl<$($t),+> IntoValue for ($($t,)+) where $($t: IntoValue,)+ {
fn into_value(self, span: Span) -> Value {
let vals = vec![$(self.$n.into_value(span)),+];
Value::list(vals, span)
}
}
}
}
tuple_into_value!(T0:0);
tuple_into_value!(T0:0, T1:1);
tuple_into_value!(T0:0, T1:1, T2:2);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
tuple_into_value!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10);
tuple_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);
impl IntoValue for String {
fn into_value(self, span: Span) -> Value {
Value::string(self, span)
}
}
impl<T> IntoValue for Vec<T>
where
T: IntoValue,
{
fn into_value(self, span: Span) -> Value {
Value::list(self.into_iter().map(|v| v.into_value(span)).collect(), span)
}
}
impl<T> IntoValue for Option<T>
where
T: IntoValue,
{
fn into_value(self, span: Span) -> Value {
match self {
Some(v) => v.into_value(span),
None => Value::nothing(span),
}
}
}
impl<V> IntoValue for HashMap<String, V>
where
V: IntoValue,
{
fn into_value(self, span: Span) -> Value {
let mut record = Record::new();
for (k, v) in self.into_iter() {
record.push(k, v.into_value(span));
}
Value::record(record, span)
}
}
impl IntoValue for Value {
fn into_value(self, span: Span) -> Value {
self.with_span(span)
}
}
pub trait TryIntoValue: Sized {
fn try_into_value(self, span: Span) -> Result<Value, ShellError>;
}
impl<T> TryIntoValue for T
where
T: IntoValue,
{
fn try_into_value(self, span: Span) -> Result<Value, ShellError> {
Ok(self.into_value(span))
}
}