├── .gitignore ├── Cargo.toml ├── README.md ├── build.rs ├── header.txt ├── src └── lib.rs └── tests └── macros.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .DS_Store 4 | *.swp 5 | *.bk 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde_wat" 3 | version = "0.1.0" 4 | authors = ["Maciej Goszczycki "] 5 | build = "build.rs" 6 | description = "Scary macros for serde_json" 7 | documentation = "http://mgoszcz2.github.io/serde_wat/serde_wat/index.html" 8 | repository = "https://github.com/mgoszcz2/serde_wat" 9 | readme = "README.md" 10 | keywords = ["serde", "json", "macro"] 11 | license = "MIT" 12 | 13 | [dev-dependencies] 14 | serde_json = "0.8.1" 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scary macros for serde_json 2 | 3 |
[Documentation](http://mgoszcz2.github.io/serde_wat/serde_wat/index.html) | [Crate](https://crates.io/crates/serde_wat)
4 | 5 | ![Wat](https://i.imgur.com/IppKJ.jpg) 6 | 7 | Macros for easily accessing `serde_json` 8 | [Value](https://docs.serde.rs/serde_json/value/enum.Value.html)s 9 | in JavaScript like fashion 10 | 11 | ```toml 12 | # Cargo.toml 13 | [dependencies] 14 | serde_wat = "0.1" 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```rust 20 | #[macro_use] extern crate serde_wat; 21 | extern crate serde_json; 22 | 23 | use serde_json::from_str; 24 | use serde_json::value::Value; 25 | 26 | let a: Value = from_str(r#"{"b": {"c": 42}}"#).unwrap(); 27 | // Access unwrapping 28 | assert_eq!(wat!(a.b.c as i64), 42); 29 | // Safe access 30 | assert_eq!(wat!(a.b as &str?), None); 31 | // Testing 32 | assert_eq!(wat!(a is bool), false); 33 | ``` 34 | 35 | ## Examples 36 | 37 | ```rust 38 | wat!(a.b.c as i64); 39 | wat!(a as &mut Vec?); 40 | wat!(a as &str); 41 | wat!(a.b is i64); 42 | wat!(a.b is &Map?); 43 | wat!(a is &Map); 44 | wat!(a.0 as bool); 45 | ``` 46 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::Path; 5 | 6 | macro_rules! generate_getters { 7 | ($fd:ident: $($x:ty => $y:ident ($z:ident)),+,) => {{ 8 | $( 9 | generate_getter(&mut $fd, stringify!($x), stringify!($y)); 10 | generate_checker(&mut $fd, stringify!($x), stringify!($z)); 11 | )* 12 | }} 13 | } 14 | 15 | fn generate_getter(fd: &mut File, typ: &str, method: &str) { 16 | // Normal getter 17 | fd.write_fmt(format_args!("\n($var:tt.$($x:tt).* as {}) => {{ 18 | wat!($var.$($x).*).as_{}().unwrap() 19 | }};\n", typ, method)).unwrap(); 20 | 21 | // Normal safe getter 22 | fd.write_fmt(format_args!("\n($var:tt.$($x:tt).* as {}?) => {{ 23 | wat!($var.$($x).*?).and_then(|x| x.as_{}()) 24 | }};\n", typ, method)).unwrap(); 25 | 26 | // Top level getter 27 | fd.write_fmt(format_args!("\n($var:tt as {}) => {{ 28 | $var.as_{}().unwrap() 29 | }};\n", typ, method)).unwrap(); 30 | 31 | // Top level safe getter 32 | fd.write_fmt(format_args!("\n($var:tt as {}?) => {{ 33 | $var.as_{}() 34 | }};\n", typ, method)).unwrap(); 35 | } 36 | 37 | fn generate_checker(fd: &mut File, typ: &str, method: &str) { 38 | // Normal check 39 | fd.write_fmt(format_args!("\n($var:tt.$($x:tt).* is {}) => {{ 40 | wat!($var.$($x).*).is_{}() 41 | }};\n", typ, method)).unwrap(); 42 | 43 | // Safe check 44 | fd.write_fmt(format_args!("\n($var:tt.$($x:tt).* is {}?) => {{ 45 | wat!($var.$($x).*?).map_or(false, |x| x.is_{}()) 46 | }};\n", typ, method)).unwrap(); 47 | 48 | // Top level check 49 | fd.write_fmt(format_args!("\n($var:tt is {}) => {{ 50 | $var.is_{}() 51 | }};\n", typ, method)).unwrap(); 52 | // Top level safe check would be silly.. there are no keys to lookup 53 | } 54 | 55 | fn main() { 56 | let out_dir = env::var("OUT_DIR").unwrap(); 57 | let dest_path = Path::new(&out_dir).join("macros.rs"); 58 | let mut fd = File::create(&dest_path).unwrap(); 59 | fd.write_all(include_bytes!("header.txt")).unwrap(); 60 | 61 | generate_getters! {fd: 62 | &Vec => array (array), 63 | i64 => i64 (number), 64 | u64 => u64 (number), 65 | i64 => i64 (number), 66 | &Map => object (object), 67 | bool => bool (boolean), 68 | &str => str (string), 69 | () => null (null), 70 | } 71 | generate_getter(&mut fd, "&mut Vec", "array_mut"); 72 | generate_getter(&mut fd, "&mut Map", "object_mut"); 73 | 74 | fd.write_all(b"}").unwrap(); 75 | } 76 | -------------------------------------------------------------------------------- /header.txt: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! wat { 3 | ($var:tt.$($x:tt).+) => {{ 4 | let path = "/".to_string() + &[$(stringify!($x)),*].join("/"); 5 | $var.pointer(&path).expect(&format!("Key error {}", path)) 6 | }}; 7 | ($var:tt.$($x:tt).+?) => {{ 8 | let path = "/".to_string() + &[$(stringify!($x)),*].join("/"); 9 | $var.pointer(&path) 10 | }}; 11 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Scary macros for serde_json 2 | //! ![Wat](https://i.imgur.com/IppKJ.jpg) 3 | //! 4 | //! Macros for easily accessing `serde_json` 5 | //! [Value](https://docs.serde.rs/serde_json/value/enum.Value.html)s 6 | //! in JavaScript like fashion 7 | //! 8 | //! ```rust 9 | //! #[macro_use] extern crate serde_wat; 10 | //! extern crate serde_json; 11 | //! 12 | //! use serde_json::from_str; 13 | //! use serde_json::value::Value; 14 | //! 15 | //! # fn main() { 16 | //! let a: Value = from_str(r#"{"b": {"c": 42}}"#).unwrap(); 17 | //! // Access unwrapping 18 | //! assert_eq!(wat!(a.b.c as i64), 42); 19 | //! // Safe access 20 | //! assert_eq!(wat!(a.b as &str?), None); 21 | //! // Testing 22 | //! assert_eq!(wat!(a is bool), false); 23 | //! # } 24 | //! ``` 25 | //! 26 | //! ## Examples 27 | //! 28 | //! ```rust,ignore 29 | //! wat!(a.b.c as i64); 30 | //! wat!(a as &mut Vec?); 31 | //! wat!(a as &str); 32 | //! wat!(a.b is i64); 33 | //! wat!(a.b is &Map?); 34 | //! wat!(a is &Map); 35 | //! wat!(a.0 as bool); 36 | //! ``` 37 | 38 | // Generated by build.rs 39 | include!(concat!(env!("OUT_DIR"), "/macros.rs")); 40 | -------------------------------------------------------------------------------- /tests/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_wat; 3 | extern crate serde_json; 4 | 5 | use serde_json::from_str; 6 | use serde_json::value::Value; 7 | 8 | #[test] 9 | fn lookup() { 10 | let a: Value = from_str(r#"{"b": {"c": 42}}"#).unwrap(); 11 | assert_eq!(wat!(a.b.c as i64), 42) 12 | } 13 | 14 | #[test] 15 | fn lookup_mut() { 16 | let mut a: Value = from_str("[null]").unwrap(); 17 | assert_eq!(wat!(a as &mut Vec), &mut [Value::Null]); 18 | } 19 | 20 | #[test] 21 | fn cast() { 22 | let a: Value = from_str("\"\"").unwrap(); 23 | assert_eq!(wat!(a as &str), "") 24 | } 25 | 26 | #[test] 27 | fn check() { 28 | let a: Value = from_str(r#"{"b": 42}"#).unwrap(); 29 | assert!(wat!(a.b is i64)) 30 | } 31 | 32 | #[test] 33 | fn check_map() { 34 | let a: Value = from_str(r#"{"b": {}}"#).unwrap(); 35 | assert!(wat!(a.b is &Map)) 36 | } 37 | 38 | #[test] 39 | fn check_toplevel() { 40 | let a: Value = from_str(r#"{}"#).unwrap(); 41 | assert!(wat!(a is &Map)) 42 | } 43 | 44 | #[test] 45 | fn lookup_index() { 46 | let a: Value = from_str("[true]").unwrap(); 47 | assert!(wat!(a.0 as bool)) 48 | } 49 | 50 | #[test] 51 | fn safe_null_check() { 52 | let a: Value = from_str("{}").unwrap(); 53 | assert_eq!(wat!(a.b is ()?), false) 54 | } 55 | 56 | #[test] 57 | fn safe_null_get() { 58 | let a: Value = from_str("{}").unwrap(); 59 | assert_eq!(wat!(a.b as ()?), None) 60 | } 61 | 62 | #[test] 63 | fn safe_top_level_get() { 64 | let a: Value = from_str("{}").unwrap(); 65 | assert_eq!(wat!(a as ()?), None) 66 | } 67 | 68 | #[test] 69 | fn just_none() { 70 | let a: Value = from_str(r#"{"b": {"c": 42}}"#).unwrap(); 71 | assert_eq!(wat!(a.b as &str?), None); 72 | } 73 | --------------------------------------------------------------------------------