nushell/src/object/base.rs

262 lines
8.9 KiB
Rust
Raw Normal View History

2019-05-12 00:59:57 +02:00
use crate::errors::ShellError;
2019-05-10 18:59:12 +02:00
use crate::object::desc::DataDescriptor;
2019-05-16 00:23:36 +02:00
use ansi_term::Color;
use chrono::{DateTime, Utc};
use chrono_humanize::Humanize;
use std::time::SystemTime;
2019-05-10 18:59:12 +02:00
2019-05-17 17:55:50 +02:00
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
2019-05-10 18:59:12 +02:00
pub enum Primitive {
Nothing,
Int(i64),
2019-05-16 00:58:44 +02:00
#[allow(unused)]
2019-05-17 17:55:50 +02:00
Float(ordered_float::OrderedFloat<f64>),
Bytes(u128),
2019-05-10 18:59:12 +02:00
String(String),
Boolean(bool),
Date(DateTime<Utc>),
2019-05-10 18:59:12 +02:00
}
impl Primitive {
crate fn format(&self, field_name: Option<&str>) -> String {
2019-05-10 18:59:12 +02:00
match self {
2019-05-16 00:23:36 +02:00
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
Primitive::Bytes(b) => {
let byte = byte_unit::Byte::from_bytes(*b);
2019-05-16 00:23:36 +02:00
if byte.get_bytes() == 0u128 {
return Color::Black.bold().paint("Empty".to_string()).to_string();
}
let byte = byte.get_appropriate_unit(true);
match byte.get_unit() {
byte_unit::ByteUnit::B => format!("{}", byte.format(0)),
_ => format!("{}", byte.format(1)),
}
}
2019-05-10 18:59:12 +02:00
Primitive::Int(i) => format!("{}", i),
Primitive::Float(f) => format!("{}", f),
Primitive::String(s) => format!("{}", s),
Primitive::Boolean(b) => match (b, field_name) {
(true, None) => format!("Yes"),
(false, None) => format!("No"),
(true, Some(s)) => format!("{}", s),
2019-05-16 00:58:44 +02:00
(false, Some(_)) => format!(""),
},
2019-05-16 00:23:36 +02:00
Primitive::Date(d) => format!("{}", d.humanize()),
2019-05-10 18:59:12 +02:00
}
}
}
2019-05-17 17:55:50 +02:00
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
2019-05-10 18:59:12 +02:00
pub enum Value {
Primitive(Primitive),
Object(crate::object::Dictionary),
2019-05-10 18:59:12 +02:00
List(Vec<Value>),
2019-05-17 17:30:10 +02:00
#[allow(unused)]
Error(Box<ShellError>),
2019-05-10 18:59:12 +02:00
}
2019-05-16 00:23:36 +02:00
impl Value {
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
2019-05-10 18:59:12 +02:00
match self {
2019-05-16 00:58:44 +02:00
Value::Primitive(_) => vec![],
2019-05-10 18:59:12 +02:00
Value::Object(o) => o.data_descriptors(),
2019-05-16 00:58:44 +02:00
Value::List(_) => vec![],
Value::Error(_) => vec![],
2019-05-10 18:59:12 +02:00
}
}
2019-05-17 17:55:50 +02:00
crate fn get_data_by_key(&'a self, name: &str) -> crate::MaybeOwned<'a, Value> {
match self {
Value::Primitive(_) => crate::MaybeOwned::Owned(Value::nothing()),
Value::Object(o) => o.get_data_by_key(name),
Value::List(_) => crate::MaybeOwned::Owned(Value::nothing()),
Value::Error(_) => crate::MaybeOwned::Owned(Value::nothing()),
}
}
2019-05-16 00:23:36 +02:00
crate fn get_data(&'a self, desc: &DataDescriptor) -> crate::MaybeOwned<'a, Value> {
2019-05-10 18:59:12 +02:00
match self {
2019-05-16 00:58:44 +02:00
Value::Primitive(_) => crate::MaybeOwned::Owned(Value::nothing()),
2019-05-10 18:59:12 +02:00
Value::Object(o) => o.get_data(desc),
2019-05-16 00:58:44 +02:00
Value::List(_) => crate::MaybeOwned::Owned(Value::nothing()),
Value::Error(_) => crate::MaybeOwned::Owned(Value::nothing()),
}
}
2019-05-16 00:23:36 +02:00
crate fn copy(&self) -> Value {
match self {
Value::Primitive(p) => Value::Primitive(p.clone()),
Value::Object(o) => Value::Object(o.copy_dict()),
Value::List(l) => {
let list = l.iter().map(|i| i.copy()).collect();
Value::List(list)
}
Value::Error(e) => Value::Error(Box::new(e.copy_error())),
2019-05-10 18:59:12 +02:00
}
}
crate fn format_leaf(&self, field_name: Option<&str>) -> String {
2019-05-10 18:59:12 +02:00
match self {
Value::Primitive(p) => p.format(field_name),
2019-05-16 00:58:44 +02:00
Value::Object(_) => format!("[object Object]"),
Value::List(_) => format!("[list List]"),
Value::Error(e) => format!("{}", e),
2019-05-10 18:59:12 +02:00
}
}
2019-05-12 00:59:57 +02:00
crate fn as_string(&self) -> Result<String, ShellError> {
match self {
Value::Primitive(Primitive::String(s)) => Ok(s.to_string()),
// TODO: this should definitely be more general with better errors
other => Err(ShellError::string(format!(
"Expected string, got {:?}",
other
))),
2019-05-12 00:59:57 +02:00
}
}
2019-05-15 18:12:38 +02:00
crate fn as_int(&self) -> Result<i64, ShellError> {
match self {
Value::Primitive(Primitive::Int(i)) => Ok(*i),
// TODO: this should definitely be more general with better errors
other => Err(ShellError::string(format!(
"Expected integer, got {:?}",
other
))),
}
}
2019-05-16 23:43:36 +02:00
#[allow(unused)]
2019-05-16 04:42:44 +02:00
crate fn as_bool(&self) -> Result<bool, ShellError> {
match self {
Value::Primitive(Primitive::Boolean(b)) => Ok(*b),
// TODO: this should definitely be more general with better errors
other => Err(ShellError::string(format!(
"Expected integer, got {:?}",
other
))),
}
}
2019-05-10 18:59:12 +02:00
crate fn string(s: impl Into<String>) -> Value {
Value::Primitive(Primitive::String(s.into()))
}
crate fn bytes(s: impl Into<u128>) -> Value {
Value::Primitive(Primitive::Bytes(s.into()))
}
2019-05-10 18:59:12 +02:00
crate fn int(s: impl Into<i64>) -> Value {
Value::Primitive(Primitive::Int(s.into()))
}
2019-05-16 23:43:36 +02:00
#[allow(unused)]
2019-05-16 04:42:44 +02:00
crate fn bool(s: impl Into<bool>) -> Value {
Value::Primitive(Primitive::Boolean(s.into()))
}
crate fn system_date(s: SystemTime) -> Value {
Value::Primitive(Primitive::Date(s.into()))
}
2019-05-17 17:30:10 +02:00
#[allow(unused)]
crate fn system_date_result(s: Result<SystemTime, std::io::Error>) -> Value {
match s {
Ok(time) => Value::Primitive(Primitive::Date(time.into())),
Err(err) => Value::Error(Box::new(ShellError::string(format!("{}", err)))),
}
}
2019-05-10 18:59:12 +02:00
crate fn boolean(s: impl Into<bool>) -> Value {
Value::Primitive(Primitive::Boolean(s.into()))
}
crate fn nothing() -> Value {
Value::Primitive(Primitive::Nothing)
}
2019-05-16 00:58:44 +02:00
#[allow(unused)]
2019-05-10 18:59:12 +02:00
crate fn list(values: impl Into<Vec<Value>>) -> Value {
Value::List(values.into())
}
}
2019-05-16 00:23:36 +02:00
crate fn select(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
let mut out = crate::object::Dictionary::default();
let descs = obj.data_descriptors();
for field in fields {
match descs.iter().find(|d| d.name == *field) {
None => out.add(field.to_string(), Value::nothing()),
Some(desc) => out.add(field.to_string(), obj.get_data(desc).borrow().copy()),
}
}
out
2019-05-10 18:59:12 +02:00
}
2019-05-16 00:23:36 +02:00
crate fn reject(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
let mut out = crate::object::Dictionary::default();
let descs = obj.data_descriptors();
for desc in descs {
if fields.contains(&desc.name) {
continue;
} else {
out.add(desc.name.clone(), obj.get_data(&desc).borrow().copy())
}
}
out
}
2019-05-16 04:42:44 +02:00
crate fn find(obj: &Value, field: &str, op: &str, rhs: &Value) -> bool {
let descs = obj.data_descriptors();
match descs.iter().find(|d| d.name == *field) {
None => false,
Some(desc) => {
let v = obj.get_data(desc).borrow().copy();
//println!("'{:?}' '{}' '{:?}'", v, op, rhs);
match v {
2019-05-16 23:43:36 +02:00
Value::Primitive(Primitive::Boolean(b)) => match (op, rhs) {
("-eq", Value::Primitive(Primitive::Boolean(b2))) => b == *b2,
("-ne", Value::Primitive(Primitive::Boolean(b2))) => b != *b2,
_ => false,
},
Value::Primitive(Primitive::Bytes(i)) => match (op, rhs) {
("-lt", Value::Primitive(Primitive::Int(i2))) => i < (*i2 as u128),
("-gt", Value::Primitive(Primitive::Int(i2))) => i > (*i2 as u128),
("-le", Value::Primitive(Primitive::Int(i2))) => i <= (*i2 as u128),
("-ge", Value::Primitive(Primitive::Int(i2))) => i >= (*i2 as u128),
("-eq", Value::Primitive(Primitive::Int(i2))) => i == (*i2 as u128),
("-ne", Value::Primitive(Primitive::Int(i2))) => i != (*i2 as u128),
_ => false,
},
Value::Primitive(Primitive::Int(i)) => match (op, rhs) {
("-lt", Value::Primitive(Primitive::Int(i2))) => i < *i2,
("-gt", Value::Primitive(Primitive::Int(i2))) => i > *i2,
("-le", Value::Primitive(Primitive::Int(i2))) => i <= *i2,
("-ge", Value::Primitive(Primitive::Int(i2))) => i >= *i2,
("-eq", Value::Primitive(Primitive::Int(i2))) => i == *i2,
("-ne", Value::Primitive(Primitive::Int(i2))) => i != *i2,
_ => false,
},
Value::Primitive(Primitive::String(s)) => match (op, rhs) {
("-eq", Value::Primitive(Primitive::String(s2))) => s == *s2,
("-ne", Value::Primitive(Primitive::String(s2))) => s != *s2,
_ => false,
},
2019-05-16 04:42:44 +02:00
_ => false,
}
}
}
}