1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use std::collections::BTreeMap; #[macro_export] macro_rules! proto_object { ($($obj:tt)+) => { object_internal!($($obj)+) }; } #[macro_export(local_inner_macros)] macro_rules! object_internal { (@array [$($elems:expr,)*]) => { object_internal_vec!($($elems,)*) }; (@array [$($elems:expr),*]) => { object_internal_vec!($($elems),*) }; (@object $object:ident () () ()) => {}; (@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => { $object.push(($($key)+, $value)); object_internal!(@object $object () ($($rest)*) ($($rest)*)); }; (@object $object:ident [$($key:tt)+] ($value:expr)) => { $object.push(($($key)+, $value)); }; (@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => { object_internal!(@object $object [$($key)+] (object_single_value!(true)) $($rest)*); }; (@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => { object_internal!(@object $object [$($key)+] (object_single_value!(false)) $($rest)*); }; (@object $object:ident ($($key:tt)+) (: $value:expr, $($rest:tt)*) $copy:tt) => { object_internal!(@object $object [$($key)+] (object_single_value!($value)), $($rest)*); }; (@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => { object_internal!(@object $object [$($key)+] (object_single_value!($value))); }; (@object $object:ident () (: $(rest:tt)*) ($colon:tt $($copy:tt)*)) => { object_unexpected($colon); }; (@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => { object_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*)); }; (@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => { object_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*)); }; ({ $($tt:tt)+ }) => { { let mut object = Vec::<(&str, &str)>::new(); object_internal!(@object object () ($($tt)+) ($($tt)+)); $crate::QueryParams{ inner: object } } }; } #[macro_export] macro_rules! object_single_value { (true) => { "true" }; (false) => { "false" }; ({}) => { "" }; ([]) => { "" }; ([ $(tt:tt)+ ]) => { object_internal!(@array [] $($tt)+ ) }; ($expr:expr) => { stringify!($expr).trim_matches('"') } } #[macro_export] macro_rules! object_internal_vec { ($($vec:tt)*) => { vec![$($vec)*] }; } #[macro_export] macro_rules! object_unexpected { () => {}; } #[test] fn test() { let val = proto_object!({ "rust": true, "lumin": [1,2,3,123], "test_string": "hello" } ); println!("value={:?}", val); }