json_codec_wasm/
macros.rs

1#[macro_export]
2/// Macro to support extraction of subsets of JSON object fields.
3///
4/// Optionally `extract!` accepts a `Utf8Buffer` to use when
5/// decoding object keys.
6///
7/// # Example:
8///
9/// ```
10/// #
11/// #[macro_use] extern crate json_codec_wasm;
12/// # fn main() {
13///
14/// use json_codec_wasm::Decoder;
15///
16/// let mut d = Decoder::default(r#"{"x": 0, "y": 1}"#.chars());
17///
18/// let p = extract! {
19///     let decoder = d;
20///     x: req. u32 = "x" => d.from_json(),
21///     y: req. u32 = "y" => d.from_json()
22/// }.unwrap();
23///
24/// assert_eq!(0, p.x);
25/// assert_eq!(1, p.y);
26/// # }
27/// ```
28macro_rules! extract {
29    (
30      let decoder = $dec: ident;
31      let buffer  = $buf: expr;
32      $($name: ident: $modus: ident. $typ: ty = $key: expr => $action: expr),+
33    ) => {{
34        struct X {
35            $($name: $typ),+
36        }
37        object! {
38            let decoder = $dec;
39            let buffer  = &mut $buf;
40            X {
41                $($name: $modus. $key => $action),+
42            }
43        }
44    }};
45    (
46      let decoder = $dec: ident;
47      $($name: ident: $modus: ident. $typ: ty = $key: expr => $action: expr),+
48    ) => {{
49        struct X {
50            $($name: $typ),+
51        }
52        object! {
53            let decoder = $dec;
54            X {
55                $($name: $modus. $key => $action),+
56            }
57        }
58    }};
59}
60
61#[macro_export]
62/// Macro to support declarative decoding into struct types.
63///
64/// Optionally `object!` accepts a `Utf8Buffer` to use when
65/// decoding object keys.
66///
67/// # Example:
68///
69/// ```
70/// #
71/// #[macro_use] extern crate json_codec_wasm;
72/// # fn main() {
73///
74/// use json_codec_wasm::Decoder;
75///
76/// #[derive(Debug, PartialEq)]
77/// struct Point {
78///     x: u32,
79///     y: u32
80/// }
81///
82/// let mut d = Decoder::default(r#"{"x": 0, "y": 1}"#.chars());
83///
84/// let p = object! {
85///     let decoder = d;
86///     Point {
87///         x: req. "x" => d.u32(),
88///         y: req. "y" => d.u32()
89///     }
90/// };
91///
92/// assert_eq!(Some(Point { x: 0, y: 1}), p.ok());
93/// # }
94/// ```
95macro_rules! object {
96    (
97      let decoder = $dec: ident;
98      let buffer  = $buf: expr;
99      $T: ident {
100          $($name: ident: $modus: ident. $key: expr => $action: expr),+
101      }
102    ) => {{
103        $dec.object().and_then(|()| {
104            $(let mut $name = None;)+
105            while $dec.has_more()? {
106                $buf.reset();
107                $dec.key_str($buf, false)?;
108                match $buf.as_str() {
109                    $($key => { $name = Some($action?) })+
110                    _      => { $dec.skip()? }
111                }
112            }
113            Ok($T {
114                $($name: to_field!($key, $name, $modus),)+
115            })
116        })
117    }};
118    (
119      let decoder = $dec: ident;
120      $T: ident {
121          $($name: ident: $modus: ident. $key: expr => $action: expr),+
122      }
123    ) => {{
124        $dec.object().and_then(|()| {
125            $(let mut $name = None;)+
126            while $dec.has_more()? {
127                match $dec.key()?.as_ref() {
128                    $($key => { $name = Some($action?) })+
129                    _      => { $dec.skip()? }
130                }
131            }
132            Ok($T {
133                $($name: to_field!($key, $name, $modus),)+
134            })
135        })
136    }};
137}
138
139#[macro_export]
140macro_rules! to_field {
141    ($msg: expr, $e: expr, opt) => {
142        match $e {
143            Some(e) => e,
144            None => None,
145        }
146    };
147    ($msg: expr, $e: expr, req) => {
148        match $e {
149            Some(e) => e,
150            None => return Err($crate::DecodeError::Expected($msg)),
151        }
152    };
153}
154
155#[macro_export]
156/// Macro to support declarative decoding into `Vec`.
157///
158/// This only supports homogenous JSON arrays. To decode
159/// arrays with different element types use `Decoder::array`.
160macro_rules! array {
161    ($dec: ident, $action: expr) => {{
162        $dec.array().and_then(|()| {
163            let mut v = Vec::new();
164            while $dec.has_more()? {
165                v.push($action?)
166            }
167            Ok(v)
168        })
169    }};
170}