Merge pull request #36 from jonathandturner/json_support

Add json support
This commit is contained in:
Jonathan Turner 2019-05-28 14:04:43 +12:00 committed by GitHub
commit 543349224a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 96 additions and 6 deletions

3
Cargo.lock generated
View File

@ -1012,6 +1012,9 @@ dependencies = [
"prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -37,6 +37,9 @@ log = "0.4.6"
pretty_env_logger = "0.3.0" pretty_env_logger = "0.3.0"
lalrpop-util = "0.17.0" lalrpop-util = "0.17.0"
regex = "1.1.6" regex = "1.1.6"
serde = "1.0.91"
serde_json = "1.0.39"
serde_derive = "1.0.91"
[dependencies.pancurses] [dependencies.pancurses]
version = "0.16" version = "0.16"

View File

@ -48,10 +48,13 @@ pub async fn cli() -> Result<(), Box<Error>> {
("view", Arc::new(view::view)), ("view", Arc::new(view::view)),
("skip", Arc::new(skip::skip)), ("skip", Arc::new(skip::skip)),
("first", Arc::new(take::take)), ("first", Arc::new(take::take)),
("select", Arc::new(select::select)), ("from-json", Arc::new(from_json::from_json)),
("open", Arc::new(open::open)),
("column", Arc::new(select::select)),
("split", Arc::new(split::split)), ("split", Arc::new(split::split)),
("reject", Arc::new(reject::reject)), ("reject", Arc::new(reject::reject)),
("to-array", Arc::new(to_array::to_array)), ("to-array", Arc::new(to_array::to_array)),
("to-json", Arc::new(to_json::to_json)),
("where", Arc::new(where_::r#where)), ("where", Arc::new(where_::r#where)),
("sort-by", Arc::new(sort_by::sort_by)), ("sort-by", Arc::new(sort_by::sort_by)),
]); ]);

View File

@ -2,7 +2,9 @@ crate mod args;
crate mod cd; crate mod cd;
crate mod classified; crate mod classified;
crate mod command; crate mod command;
crate mod from_json;
crate mod ls; crate mod ls;
crate mod open;
crate mod ps; crate mod ps;
crate mod reject; crate mod reject;
crate mod select; crate mod select;
@ -11,6 +13,7 @@ crate mod sort_by;
crate mod split; crate mod split;
crate mod take; crate mod take;
crate mod to_array; crate mod to_array;
crate mod to_json;
crate mod view; crate mod view;
crate mod where_; crate mod where_;

View File

@ -19,7 +19,22 @@ pub fn split(args: CommandArgs) -> Result<OutputStream, ShellError> {
debug!("split result = {:?}", split_result); debug!("split result = {:?}", split_result);
if split_result.len() == (args.len() - 1) { // If they didn't provide column names, make up our own
if (args.len() - 1) == 0 {
let mut gen_columns = vec![];
for i in 0..split_result.len() {
gen_columns.push(format!("Column{}", i + 1));
}
let mut dict = crate::object::Dictionary::default();
for (k, v) in split_result.iter().zip(gen_columns.iter()) {
dict.add(
v.clone(),
Value::Primitive(Primitive::String(k.to_string())),
);
}
ReturnValue::Value(Value::Object(dict))
} else if split_result.len() == (args.len() - 1) {
let mut dict = crate::object::Dictionary::default(); let mut dict = crate::object::Dictionary::default();
for (k, v) in split_result.iter().zip(args.iter().skip(1)) { for (k, v) in split_result.iter().zip(args.iter().skip(1)) {
dict.add( dict.add(

View File

@ -1,9 +1,9 @@
#[allow(unused)] #[allow(unused)]
use crate::prelude::*; use crate::prelude::*;
use serde_derive::Serialize;
use derive_new::new; use derive_new::new;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new, Clone)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new, Clone, Serialize)]
pub struct ShellError { pub struct ShellError {
title: String, title: String,
error: Value, error: Value,

View File

@ -9,6 +9,9 @@ use derive_new::new;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use std::time::SystemTime; use std::time::SystemTime;
use serde::{Serialize, Serializer};
use serde_derive::Serialize;
type OF64 = OrderedFloat<f64>; type OF64 = OrderedFloat<f64>;
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
@ -23,6 +26,23 @@ pub enum Primitive {
Date(DateTime<Utc>), Date(DateTime<Utc>),
} }
impl Serialize for Primitive {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Primitive::Nothing => serializer.serialize_i32(0),
Primitive::Int(i) => serializer.serialize_i64(*i),
Primitive::Float(f) => serializer.serialize_f64(f.into_inner()),
Primitive::Bytes(b) => serializer.serialize_u128(*b),
Primitive::String(ref s) => serializer.serialize_str(s),
Primitive::Boolean(b) => serializer.serialize_bool(*b),
Primitive::Date(d) => serializer.serialize_str(&d.to_string()),
}
}
}
impl Primitive { impl Primitive {
crate fn format(&self, field_name: Option<&str>) -> String { crate fn format(&self, field_name: Option<&str>) -> String {
match self { match self {
@ -55,7 +75,7 @@ impl Primitive {
} }
} }
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
pub struct Operation { pub struct Operation {
crate left: Value, crate left: Value,
crate operator: Operator, crate operator: Operator,
@ -73,6 +93,21 @@ pub enum Value {
Error(Box<ShellError>), Error(Box<ShellError>),
} }
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Value::Primitive(p) => p.serialize(serializer),
Value::Object(o) => o.serialize(serializer),
Value::List(l) => l.serialize(serializer),
Value::Operation(o) => o.serialize(serializer),
Value::Error(e) => e.serialize(serializer),
}
}
}
impl Value { impl Value {
crate fn from_leaf(leaf: &tokens::Leaf) -> Value { crate fn from_leaf(leaf: &tokens::Leaf) -> Value {
use tokens::*; use tokens::*;

View File

@ -1,5 +1,6 @@
use crate::object::types::{AnyShell, Type}; use crate::object::types::{AnyShell, Type};
use derive_new::new; use derive_new::new;
use serde::{Serialize, Serializer};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DescriptorName { pub enum DescriptorName {
@ -37,6 +38,18 @@ pub struct DataDescriptor {
crate ty: Box<dyn Type>, crate ty: Box<dyn Type>,
} }
impl Serialize for DataDescriptor {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.name {
DescriptorName::String(ref s) => serializer.serialize_str(s),
DescriptorName::ValueOf => serializer.serialize_str("value_of")
}
}
}
impl From<&str> for DataDescriptor { impl From<&str> for DataDescriptor {
fn from(input: &str) -> DataDescriptor { fn from(input: &str) -> DataDescriptor {
DataDescriptor { DataDescriptor {

View File

@ -3,6 +3,7 @@ use crate::prelude::*;
use crate::object::DataDescriptor; use crate::object::DataDescriptor;
use crate::object::{Primitive, Value}; use crate::object::{Primitive, Value};
use indexmap::IndexMap; use indexmap::IndexMap;
use serde::ser::{Serialize, Serializer, SerializeMap};
use std::cmp::{Ordering, PartialOrd}; use std::cmp::{Ordering, PartialOrd};
#[derive(Debug, Default, Eq, PartialEq, Clone)] #[derive(Debug, Default, Eq, PartialEq, Clone)]
@ -10,6 +11,19 @@ pub struct Dictionary {
entries: IndexMap<DataDescriptor, Value>, entries: IndexMap<DataDescriptor, Value>,
} }
impl Serialize for Dictionary {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(self.entries.len()))?;
for (k, v) in &self.entries {
map.serialize_entry(&k, &v)?;
}
map.end()
}
}
impl PartialOrd for Dictionary { impl PartialOrd for Dictionary {
// TODO: FIXME // TODO: FIXME
fn partial_cmp(&self, _other: &Dictionary) -> Option<Ordering> { fn partial_cmp(&self, _other: &Dictionary) -> Option<Ordering> {

View File

@ -1,7 +1,8 @@
use derive_new::new; use derive_new::new;
use std::str::FromStr; use std::str::FromStr;
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
pub enum Operator { pub enum Operator {
Equal, Equal,
NotEqual, NotEqual,