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);
}