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}