You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.4 KiB
Rust
213 lines
6.4 KiB
Rust
use nu_protocol::{Record, Span, Value};
|
|
use rusty_value::{Fields, HashableValue, RustyValue};
|
|
|
|
use crate::utils::NewEmpty;
|
|
|
|
/// A helper struct to allow IntoValue operations for nu values
|
|
pub struct RawValue(pub Value);
|
|
|
|
/// Converts the given type into a value
|
|
/// This trait is implemented for all types that
|
|
/// Implement the RustyValue trait
|
|
pub trait IntoValue {
|
|
fn into_value(self) -> Value;
|
|
}
|
|
|
|
impl IntoValue for RawValue {
|
|
#[inline]
|
|
fn into_value(self) -> Value {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
/// Helper trait to avoid conflicts
|
|
pub trait RustyIntoValue {
|
|
fn into_value(self) -> Value;
|
|
}
|
|
|
|
pub(crate) trait HashableIntoString {
|
|
fn into_string(self) -> String;
|
|
}
|
|
|
|
impl HashableIntoString for HashableValue {
|
|
fn into_string(self) -> String {
|
|
match self {
|
|
HashableValue::Primitive(p) => p.to_string(),
|
|
HashableValue::List(l) => l
|
|
.into_iter()
|
|
.map(|v| v.into_string())
|
|
.collect::<Vec<_>>()
|
|
.join(","),
|
|
HashableValue::None => String::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for Vec<Value> {
|
|
#[inline]
|
|
fn into_value(self) -> Value {
|
|
Value::List {
|
|
vals: self,
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for rusty_value::Value {
|
|
fn into_value(self) -> Value {
|
|
match self {
|
|
rusty_value::Value::Primitive(p) => p.into_value(),
|
|
rusty_value::Value::Struct(s) => {
|
|
if let Fields::Unit = &s.fields {
|
|
Value::String {
|
|
val: s.name,
|
|
internal_span: Span::empty(),
|
|
}
|
|
} else {
|
|
s.fields.into_value()
|
|
}
|
|
}
|
|
rusty_value::Value::Enum(e) => {
|
|
if let Fields::Unit = &e.fields {
|
|
Value::String {
|
|
val: e.variant,
|
|
internal_span: Span::empty(),
|
|
}
|
|
} else {
|
|
e.fields.into_value()
|
|
}
|
|
}
|
|
rusty_value::Value::Map(map) => {
|
|
let mut cols = Vec::new();
|
|
let mut vals = Vec::new();
|
|
|
|
for (key, val) in map {
|
|
cols.push(key.into_string());
|
|
vals.push(val.into_value());
|
|
}
|
|
Value::Record {
|
|
val: Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
rusty_value::Value::List(l) => {
|
|
let vals = l.into_iter().map(|e| e.into_value()).collect();
|
|
|
|
Value::List {
|
|
vals,
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
rusty_value::Value::None => Value::Nothing {
|
|
internal_span: Span::empty(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for rusty_value::Primitive {
|
|
fn into_value(self) -> Value {
|
|
match self {
|
|
rusty_value::Primitive::Integer(i) => i.into_value(),
|
|
rusty_value::Primitive::Float(f) => f.into_value(),
|
|
rusty_value::Primitive::String(val) => Value::String {
|
|
val,
|
|
internal_span: Span::empty(),
|
|
},
|
|
rusty_value::Primitive::Char(val) => Value::String {
|
|
val: val.to_string(),
|
|
internal_span: Span::empty(),
|
|
},
|
|
rusty_value::Primitive::Bool(val) => Value::Bool {
|
|
val,
|
|
internal_span: Span::empty(),
|
|
},
|
|
rusty_value::Primitive::OsString(osstr) => osstr.to_string_lossy().into_value(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for rusty_value::Fields {
|
|
fn into_value(self) -> Value {
|
|
match self {
|
|
rusty_value::Fields::Named(named) => {
|
|
let mut cols = Vec::with_capacity(named.len());
|
|
let mut vals = Vec::with_capacity(named.len());
|
|
|
|
for (k, v) in named {
|
|
cols.push(k);
|
|
vals.push(v.into_value());
|
|
}
|
|
Value::Record {
|
|
val: Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
rusty_value::Fields::Unnamed(unnamed) => {
|
|
let mut vals = unnamed
|
|
.into_iter()
|
|
.map(|v| v.into_value())
|
|
.collect::<Vec<_>>();
|
|
|
|
// newtypes should be handled differently
|
|
// and only return the inner value instead of a range of values
|
|
if vals.len() == 1 {
|
|
vals.pop().unwrap()
|
|
} else {
|
|
Value::List {
|
|
vals,
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
}
|
|
rusty_value::Fields::Unit => Value::Nothing {
|
|
internal_span: Span::empty(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for rusty_value::Integer {
|
|
fn into_value(self) -> Value {
|
|
let val = match self {
|
|
rusty_value::Integer::USize(i) => i as i64,
|
|
rusty_value::Integer::ISize(i) => i as i64,
|
|
rusty_value::Integer::U8(i) => i as i64,
|
|
rusty_value::Integer::I8(i) => i as i64,
|
|
rusty_value::Integer::U16(i) => i as i64,
|
|
rusty_value::Integer::I16(i) => i as i64,
|
|
rusty_value::Integer::U32(i) => i as i64,
|
|
rusty_value::Integer::I32(i) => i as i64,
|
|
rusty_value::Integer::U64(i) => i as i64,
|
|
rusty_value::Integer::I64(i) => i,
|
|
rusty_value::Integer::U128(i) => i as i64,
|
|
rusty_value::Integer::I128(i) => i as i64,
|
|
};
|
|
Value::Int {
|
|
val,
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RustyIntoValue for rusty_value::Float {
|
|
#[inline]
|
|
fn into_value(self) -> Value {
|
|
let val = match self {
|
|
rusty_value::Float::F32(f) => f as f64,
|
|
rusty_value::Float::F64(f) => f,
|
|
};
|
|
Value::Float {
|
|
val,
|
|
internal_span: Span::empty(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<R: RustyValue> IntoValue for R {
|
|
#[inline]
|
|
fn into_value(self) -> Value {
|
|
self.into_rusty_value().into_value()
|
|
}
|
|
}
|