telegram_api_rs/
api_macros.rs

1//! These macros are only used to create all objects easily as well as simplifying testing and creating methods.
2//////////////////////////////////////////////////////////////////////////////////////////////////////////////
3// stuff for objects
4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
5
6#[macro_export]
7macro_rules! vec_to_json_array {
8    ($($fname:ident($name:ident))*) => {
9       $(fn $fname(v: Vec<$name>) -> JsonValue {
10            let mut tmp: Vec<JsonValue> = vec![];
11            for value in v {
12                tmp.push(Custom::to_json(value));
13            }
14            let mut t = json::array![];
15            for x in tmp {
16                t.push(x).ok();
17            }
18            t
19        })*
20    }
21}
22
23#[macro_export]
24macro_rules! vec_vec_to_json_array {
25    ($($fname:ident($name:ident, $vec_func:ident))*) => {
26       $(fn $fname(v: Vec<Vec<$name>>) -> JsonValue {
27            let mut tmp: Vec<JsonValue> = vec![];
28            for value in v {
29                tmp.push($vec_func(value));
30            }
31            let mut t = json::array![];
32            for x in tmp {
33                t.push(x).ok();
34            }
35            t
36        })*
37    }
38}
39
40#[macro_export]
41macro_rules! add_functionality {
42    ($(pub struct $name:ident { $(pub $fname:ident : $ftype:ty), *})*) => {
43        $(pub struct $name {
44            $(pub $fname : $ftype), *
45        }
46
47        impl $name {
48            pub fn from_json(data: JsonValue) -> $name {
49                let mut new = $name::empty();
50                $(
51                if stringify!($fname) == "typ" {
52                    new.$fname = Custom::from_json(data["type"].clone());
53                } else {
54                    new.$fname = Custom::from_json(data[stringify!($fname)].clone());
55                }); *;
56                new
57            }
58
59             pub fn to_json(&self) -> JsonValue {
60                let mut j = json::object! {};
61                $(if stringify!($fname) == "typ" {
62                    j = Custom::create_json(j, self.$fname.clone(), "type")
63                } else {
64                    j = Custom::create_json(j, self.$fname.clone(), stringify!($fname))
65                }); *;
66                j
67            }
68
69            pub fn empty() -> $name {
70                $name {
71                    $($fname: Custom::default(), )*
72                }
73            }
74        }
75        impl fmt::Display for $name {
76            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77                let mut data = vec![];
78                $(if stringify!($fname) == "typ" {
79                    data = Custom::push(data, self.$fname.clone(), "type")
80                } else {
81                    data = Custom::push(data, self.$fname.clone(), stringify!($fname))
82                }); *;
83                write!(f, "{}", data.join("; "))
84            }
85        }
86        impl Clone for $name {
87            fn clone(&self) -> Self {
88                $name {
89                    $($fname: self.$fname.clone()), *
90                }
91            }
92        })*
93    }
94}
95
96#[macro_export]
97macro_rules! add_functionality_empty {
98    (pub struct $name:ident {}) => {
99        pub struct $name {}
100
101        impl $name {
102            pub fn from_json(_data: JsonValue) -> $name {
103                $name {}
104            }
105
106            pub fn to_json(&self) -> JsonValue {
107                JsonValue::new_object()
108            }
109
110            pub fn empty() -> $name {
111                $name {}
112            }
113        }
114        impl fmt::Display for $name {
115            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116                write!(f, "{}", "{}")
117            }
118        }
119        impl Clone for $name {
120            fn clone(&self) -> Self {
121                $name {}
122            }
123        }
124    };
125}
126
127#[macro_export]
128macro_rules! custom_from_json {
129    (fn from_json(s: JsonValue, $func:ident, $extract:ident) -> $fname:ident) => {
130        fn from_json(s: JsonValue) -> $fname {
131            s.$func().$extract()
132        }
133    };
134}
135
136#[macro_export]
137macro_rules! custom_push {
138    (fn push()) => {
139        fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
140            data.push(format!("{}: {}", name, v));
141            data
142        }
143    };
144}
145
146#[macro_export]
147macro_rules! custom_default {
148    (fn default($default:expr)) => {
149        fn default() -> Self {
150            $default
151        }
152    };
153}
154
155#[macro_export]
156macro_rules! custom_url_encode {
157    (fn url_encode(v: Self)) => {
158        fn url_encode(v: Self) -> String {
159            urlencoding::encode(&*format!("{}", Custom::to_json(v))).to_string()
160        }
161    };
162}
163
164#[macro_export]
165macro_rules! expand_custom {
166    ($(impl Custom for $fname:ident ($func:ident, $extract:ident, $default:expr))*) => {
167        $(impl Custom for $fname {
168            custom_from_json! {
169                fn from_json(s: JsonValue, $func, $extract) -> $fname
170            }
171            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
172                j.insert(name, format!("{}", v)).ok();
173                j
174            }
175            fn to_json(v: Self)  -> JsonValue {
176                JsonValue::String(format!("{}", v))
177            }
178            custom_push! {
179                fn push()
180            }
181            custom_default! {
182                fn default($default)
183            }
184            custom_url_encode! {
185                fn url_encode(v: Self)
186            }
187        })*
188    }
189}
190
191#[macro_export]
192macro_rules! expand_custom_direct_i {
193    ($(impl Custom for $fname:ident ($func:ident, $extract:ident, $default:expr))*) => {
194        $(impl Custom for $fname {
195            custom_from_json! {
196                fn from_json(s: JsonValue, $func, $extract) -> $fname
197            }
198            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
199                j.insert(name, v).ok();
200                j
201            }
202            fn to_json(v: Self)  -> JsonValue {
203                JsonValue::Number(json::number::Number::from(v as i64))
204            }
205            custom_push! {
206                fn push()
207            }
208            custom_default! {
209                fn default($default)
210            }
211            custom_url_encode! {
212                fn url_encode(v: Self)
213            }
214        })*
215    }
216}
217
218#[macro_export]
219macro_rules! expand_custom_direct_bool {
220    ($(impl Custom for $fname:ident ($func:ident, $extract:ident, $default:expr))*) => {
221        $(impl Custom for $fname {
222            custom_from_json! {
223                fn from_json(s: JsonValue, $func, $extract) -> $fname
224            }
225            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
226                j.insert(name, v).ok();
227                j
228            }
229            fn to_json(v: Self)  -> JsonValue {
230                JsonValue::Boolean(v)
231            }
232            custom_push! {
233                fn push()
234            }
235            custom_default! {
236                fn default($default)
237            }
238            custom_url_encode! {
239                fn url_encode(v: Self)
240            }
241        })*
242    }
243}
244
245#[macro_export]
246macro_rules! expand_custom_direct_object {
247    ($(impl Custom for $fname:ident ($func:ident, $extract:ident, $default:expr))*) => {
248        $(impl Custom for $fname {
249            custom_from_json! {
250                fn from_json(s: JsonValue, $func, $extract) -> $fname
251            }
252            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
253                j.insert(name, v).ok();
254                j
255            }
256            fn to_json(v: Self)  -> JsonValue {
257                v.to_json()
258            }
259            custom_push! {
260                fn push()
261            }
262            custom_default! {
263                fn default($default)
264            }
265            custom_url_encode! {
266                fn url_encode(v: Self)
267            }
268        })*
269    }
270}
271
272#[macro_export]
273macro_rules! expand_custom_vec {
274    ($(impl Custom for Vec<$fname:ident> ($func:ident, $extract:ident, $default:expr, $to_json_array:ident))*) => {
275        $(impl Custom for Vec<$fname> {
276            fn from_json(s: JsonValue) -> Vec<$fname>{
277                if !s.is_array() { [].to_vec() }
278                else {s.$func().$extract()}
279            }
280            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
281                j.insert(name, $to_json_array(v)).ok();
282                j
283            }
284            fn to_json(v: Self)  -> JsonValue {
285                JsonValue::String(format!("{}", $to_json_array(v)))
286            }
287            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
288                data.push(format!("{}: {}", name, $to_json_array(v)));
289                data
290            }
291            custom_default! {
292                fn default($default)
293            }
294            custom_url_encode! {
295                fn url_encode(v: Self)
296            }
297        })*
298    }
299}
300
301#[macro_export]
302macro_rules! expand_custom_vec_vec {
303    ($(impl Custom for Vec<Vec<$fname:ident>> ($func:ident, $extract:ident, $default:expr, $to_json_array:ident))*) => {
304        $(impl Custom for Vec<Vec<$fname>> {
305            fn from_json(s: JsonValue) -> Vec<Vec<$fname>> {
306                if !s.is_array() { $default }
307                else {s.$func().$extract()}
308            }
309            fn create_json(mut j: JsonValue, v: Self, name: &'static str)  -> JsonValue {
310                j.insert(name, $to_json_array(v)).ok();
311                j
312            }
313            fn to_json(v: Self)  -> JsonValue {
314                JsonValue::String(format!("{}", $to_json_array(v)))
315            }
316            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
317                data.push(format!("{}: {}", name, $to_json_array(v)));
318                data
319            }
320            custom_default! {
321                fn default($default)
322            }
323            custom_url_encode! {
324                fn url_encode(v: Self)
325            }
326        })*
327    }
328}
329
330#[macro_export]
331macro_rules! expand_custom_option {
332    ($(impl Custom for Option<$fname:ident> ($func:ident, $extract:ident, $default: expr))*) => {
333        $(impl Custom for Option<$fname> {
334            fn from_json(s: JsonValue) -> Option<$fname> {
335                if s.is_empty() && s.as_bool() != Some(false) { None }
336                else {Some(s.$func().$extract())}
337            }
338            fn create_json(mut j: JsonValue, v: Self, name: &'static str) -> JsonValue {
339                match v.clone() {
340                    Some(value) => {j.insert(name, value).ok();},
341                    _ => ()
342                };
343                j
344            }
345            fn to_json(v: Self)  -> JsonValue {
346                match v.clone() {
347                    Some(value) => JsonValue::String(format!("{}", value)),
348                    _ => JsonValue::Null
349                }
350
351            }
352            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
353                match v.clone() {Some(value) => data.push(format!("{}: {}", name, value)), _ => () };
354                data
355            }
356            custom_default! {
357                fn default($default)
358            }
359            custom_url_encode! {
360                fn url_encode(v: Self)
361            }
362        })*
363    }
364}
365
366#[macro_export]
367macro_rules! expand_custom_box {
368    ($(impl Custom for Box<$fname:ident> ($func:ident, $extract:ident, $default: expr))*) => {
369        $(impl Custom for Box<$fname> {
370            fn from_json(s: JsonValue) -> Box<$fname> {
371                if s.is_empty() && s.as_bool() != Some(false) { Box::new($fname::empty()) }
372                else {s.$func().$extract()}
373            }
374            fn create_json(mut j: JsonValue, v: Self, name: &'static str) -> JsonValue {
375                j.insert(name, *v).ok();
376                j
377            }
378            fn to_json(v: Self)  -> JsonValue {
379                JsonValue::String(format!("{}", *v))
380            }
381            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
382                data.push(format!("{}: {}", name, *v));
383                data
384            }
385            custom_default! {
386                fn default($default)
387            }
388            custom_url_encode! {
389                fn url_encode(v: Self)
390            }
391        })*
392    }
393}
394
395#[macro_export]
396macro_rules! expand_custom_option_box {
397    ($(impl Custom for Option<Box<$fname:ident>> ($func:ident, $extract:ident, $default: expr))*) => {
398        $(impl Custom for Option<Box<$fname>> {
399            fn from_json(s: JsonValue) -> Option<Box<$fname>> {
400                if s.is_empty() && s.as_bool() != Some(false) { None }
401                else {Some(s.$func().$extract())}
402            }
403            fn create_json(mut j: JsonValue, v: Self, name: &'static str) -> JsonValue {
404                match v.clone() {
405                    Some(value) => {j.insert(name, *value).ok();},
406                    _ => ()
407                };
408                j
409            }
410            fn to_json(v: Self)  -> JsonValue {
411                match v.clone() {
412                    Some(value) => JsonValue::String(format!("{}", *value)),
413                    _ => JsonValue::Null
414                }
415
416            }
417            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
418                match v.clone() {Some(value) => data.push(format!("{}: {}", name, *value)), _ => () };
419                data
420            }
421            custom_default! {
422                fn default($default)
423            }
424            custom_url_encode! {
425                fn url_encode(v: Self)
426            }
427        })*
428    }
429}
430
431#[macro_export]
432macro_rules! expand_custom_option_vec {
433    ($(impl Custom for Option<Vec<$fname:ident>> ($func:ident, $extract:ident, $default: expr, $to_json_array:ident))*) => {
434        $(impl Custom for Option<Vec<$fname>> {
435            fn from_json(s: JsonValue) -> Option<Vec<$fname>> {
436                if !s.is_array() { None }
437                else {Some(s.$func().$extract())}
438            }
439            fn create_json(mut j: JsonValue, v: Self, name: &'static str) -> JsonValue {
440                match v.clone() {
441                    Some(value) => {
442                        j.insert(name, $to_json_array(value)).ok();
443                    },
444                    _ => ()
445                };
446                j
447            }
448            fn to_json(v: Self)  -> JsonValue {
449                match v.clone() {
450                    Some(value) => JsonValue::String(format!("{}", $to_json_array(value))),
451                    _ => JsonValue::Null
452                }
453
454            }
455            fn push(mut data: Vec<String>, v: Self, name: &'static str) -> Vec<String> {
456                match v.clone() {
457                    Some(value) => {data.push(format!("{}: {:?}", name, $to_json_array(value)));},
458                    _ => ()
459                };
460                data
461            }
462            custom_default! {
463                fn default($default)
464            }
465            custom_url_encode! {
466                fn url_encode(v: Self)
467            }
468        })*
469    }
470}
471
472#[macro_export]
473macro_rules! as_custom {
474    ($(fn $fname:ident(&self) -> Option<$ftype:ident>)*) => {
475        $(fn $fname(&self) -> Option<$ftype> {
476            if self.is_empty() { None }
477            else { Some($ftype::from_json(self.clone())) }
478        })*
479    }
480}
481
482#[macro_export]
483macro_rules! as_box_custom {
484    ($(fn $fname:ident(&self) -> Option<Box<$ftype:ident>>)*) => {
485        $(fn $fname(&self) -> Option<Box<$ftype>> {
486            if self.is_empty() { None }
487            else { Some(Box::new($ftype::from_json(self.clone()))) }
488        })*
489    }
490}
491
492#[macro_export]
493macro_rules! as_vec_custom {
494    ($(fn $fname:ident(&self) -> Option<Vec<$ftype:ident>>)*) => {
495        $(fn $fname(&self) -> Option<Vec<$ftype>> {
496            if !self.is_array() { None }
497            else {
498                let mut ret: Vec<$ftype> = vec![];
499                let mut tmp: Vec<$ftype> = vec![];
500                let mut s = self.clone();
501                while !s.is_empty() {
502                    let t = s.pop();
503                    tmp.push($ftype::from_json(t))
504                }
505                while !tmp.is_empty() {
506                    ret.push(tmp.pop().unwrap())
507                }
508                Some(ret)
509            }
510        })*
511    }
512}
513
514#[macro_export]
515macro_rules! as_vec_vec_custom {
516    ($(fn $fname:ident(&self, $vec_func:ident) -> Option<Vec<Vec<$ftype:ident>>>)*) => {
517        $(fn $fname(&self) -> Option<Vec<Vec<$ftype>>> {
518            if !self.is_array() { None }
519            else {
520                let mut ret: Vec<Vec<$ftype>> = vec![];
521                let mut tmp: Vec<Vec<$ftype>> = vec![];
522                let mut s = self.clone();
523                while !s.is_empty() {
524                    let t = s.pop();
525                    tmp.push(t.$vec_func().unwrap())
526                }
527                while !tmp.is_empty() {
528                    ret.push(tmp.pop().unwrap())
529                }
530                Some(ret)
531            }
532        })*
533    }
534}
535
536#[macro_export]
537macro_rules! expand_from {
538    ($(impl From<$fname:ident> for JsonValue)*) => {
539        $(impl From<$fname> for JsonValue {
540            fn from(u: $fname) -> Self {
541                u.to_json()
542            }
543        })*
544    }
545}
546
547#[macro_export]
548macro_rules! expand_basic_test {
549    (fn run_test($fname:ident, $reference:expr)) => {
550        let json_me = json::parse($reference);
551        let me;
552        match json_me {
553            Ok(json_data) => me = $fname::from_json(json_data),
554            Err(_) => me = $fname::empty(),
555        }
556        let actual = format!("{}", me.to_json());
557        assert_eq!(actual, $reference);
558    };
559}
560
561//////////////////////////////////////////////////////////////////////////////////////////////////////////////
562// stuff for methods
563//////////////////////////////////////////////////////////////////////////////////////////////////////////////
564
565#[macro_export]
566macro_rules! expand_parameters_into_string {
567    ($parameters:ident, $($vname: ident), *) => {
568        $($ parameters.push_str(&*format!("{}={}&", stringify!($vname), Custom::url_encode($vname))));*
569    }
570}
571
572#[macro_export]
573macro_rules! expand_parameters_opt_into_string {
574    ($parameters:ident, $($vname: ident), *) => {
575        $(match $vname {
576            Some(v) => {
577                if stringify!($vname) == "typ" {
578                    $parameters.push_str(&*format!("typ={}&", Custom::url_encode(v)))
579                } else {
580                    $parameters.push_str(&*format!("{}={}&", stringify!($vname),Custom::url_encode(v)))
581                }},
582            None => ()
583        });*
584    }
585}
586
587#[macro_export]
588macro_rules! expand_parameters_reply_markup_into_string {
589    ($parameters:ident, $($vname: ident), *) => {
590        $(match $vname { Some(v) => $parameters.push_str(&*format!("reply_markup={}&", Custom::url_encode(v))), None => () });*
591    }
592}
593
594#[macro_export]
595macro_rules! expand_make_request_to_message {
596    ($res: ident) => {
597        if !$res["ok"].as_bool().unwrap() {
598            None
599        } else {
600            let ret: Message = Custom::from_json($res["result"].clone());
601            Some(ret)
602        }
603    };
604}
605
606#[macro_export]
607macro_rules! expand_make_request_to_bool {
608    ($res: ident) => {
609        if !$res["ok"].as_bool().unwrap() {
610            false
611        } else {
612            let ret: bool = Custom::from_json($res["result"].clone());
613            ret
614        }
615    };
616}