Last active
March 23, 2020 10:13
-
-
Save abhayarawal/a6a0504f14328e575d007e1afcbef400 to your computer and use it in GitHub Desktop.
Rust json! macro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
#[derive(Debug, PartialEq, Clone)] | |
enum Json { | |
Null, | |
Boolean(bool), | |
Number(f64), | |
String(String), | |
Array(Vec<Json>), | |
Object(Box<HashMap<String, Json>>), | |
} | |
impl From<String> for Json { | |
fn from(s: String) -> Json { | |
Json::String(s) | |
} | |
} | |
impl<'a> From<&'a str> for Json { | |
fn from(s: &'a str) -> Json { | |
Json::String(s.to_string()) | |
} | |
} | |
macro_rules! impl_num_json { | |
( $( $t:ident )+ ) => { | |
$( | |
impl From<$t> for Json { | |
fn from(n: $t) -> Json { | |
Json::Number(n as f64) | |
} | |
} | |
)+ | |
} | |
} | |
impl_num_json!(u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64); | |
macro_rules! json { | |
( null ) => { Json::Null }; | |
( true ) => { Json::Boolean(true) }; | |
( false ) => { Json::Boolean(false) }; | |
([$( $element:tt ),* ]) => { | |
Json::Array(vec![$( json!($element) ), *]) | |
}; | |
({ $( $k:tt : $v:tt ),* }) => { | |
Json::Object(Box::new( | |
vec![ | |
$( ($k.to_string(), json!($v)) ),* | |
].into_iter().collect() | |
)) | |
}; | |
( $other:tt ) => { | |
Json::from($other) | |
} | |
} | |
fn main() { | |
let js1 = Json::Array(vec![ | |
Json::Boolean(true), | |
Json::Boolean(false), | |
Json::String("hello".to_string()), | |
Json::Object(Box::new( | |
vec![( | |
"a".to_string(), | |
Json::Object(Box::new( | |
vec![( | |
"b".to_string(), | |
Json::Array(vec![Json::Null, Json::Number(90.09 as f64)]), | |
)].into_iter().collect(), | |
)), | |
)].into_iter().collect(), | |
)), | |
]); | |
println!("{:?}", js1); | |
let js2 = json!([ | |
true, | |
false, | |
"hello", | |
{ "a": { "b": [null, 90.09] } } | |
]); | |
println!("{:?}", js2); | |
} | |
#![allow(dead_code, unused)] | |
use dgraph::{make_dgraph, Dgraph, Request}; | |
use serde_derive::{Deserialize, Serialize}; | |
use serde_json::Value; | |
fn user_type() -> String { | |
"User".to_string() | |
} | |
#[derive(Debug, Default, Serialize, Deserialize)] | |
struct User { | |
uid: Option<String>, | |
name: String, | |
age: Option<u8>, | |
friends: Option<Vec<User>>, | |
#[serde(rename = "dgraph.type")] | |
#[serde(default = "user_type")] | |
dgraph_type: String, | |
} | |
fn drop_all(dg: &Dgraph) { | |
let op_clean = dgraph::Operation { | |
drop_all: true, | |
..Default::default() | |
}; | |
dg.alter(&op_clean).expect("drop schema"); | |
} | |
fn set_schema(dg: &Dgraph) { | |
let op_schema = dgraph::Operation { | |
schema: r#" | |
type User { | |
name | |
age | |
friends | |
} | |
name: string @index(exact, term) . | |
age: int . | |
friends: [uid] @reverse . | |
"# | |
.to_string(), | |
..Default::default() | |
}; | |
dg.alter(&op_schema).expect("set schema"); | |
} | |
fn insert(dg: &Dgraph, user: User) -> String { | |
let mut mutation = dgraph::Mutation::default(); | |
mutation.set_set_json(serde_json::to_vec(&user).expect("invalid json")); | |
let mut txn = dg.new_txn(); | |
let assigned = txn.mutate(mutation).expect("failed to create data"); | |
txn.commit().expect("failed to commit mutation"); | |
let mut uid: String = "".to_string(); | |
for (_, v) in assigned.uids.iter() { | |
uid = v.to_string(); | |
} | |
uid | |
} | |
macro_rules! jin { | |
[ $j:expr; $( $e:expr ),+ ] => ( | |
(|| { | |
let res = $j$(.get($e)?)+; | |
Some(res) | |
})(); | |
); | |
} | |
fn main() { | |
let dg = make_dgraph!(dgraph::new_dgraph_client("localhost:9080")); | |
// set_schema(&dg); | |
let query = r#" | |
{ | |
query(func: eq(name, "Marcella")) { | |
uid | |
name | |
age | |
friends (orderasc: age) @filter(le(age, "30")) @facets(related) { | |
uid | |
name | |
age | |
} | |
~friends { | |
uid | |
name | |
age | |
} | |
} | |
} | |
"# | |
.to_string(); | |
let resp = dg.new_readonly_txn().query(query).expect("query"); | |
let j: Value = serde_json::from_slice(&resp.json).expect("parsing"); | |
let p = jin![j; "query", 0, "friends", 0, "name"]; | |
println!( | |
"{:?}", | |
match p { | |
Some(v) => v, | |
None => &Value::Null, | |
} | |
); | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn drop_db() { | |
let dg = make_dgraph!(dgraph::new_dgraph_client("localhost:9080")); | |
// drop_all(&dg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment