1#[macro_export(local_inner_macros)]
23macro_rules! loro_value {
24 ($($json:tt)+) => {
26 value_internal!($($json)+)
27 };
28}
29
30#[macro_export(local_inner_macros)]
38#[doc(hidden)]
39macro_rules! value_internal {
40 (@array [$($elems:expr,)*]) => {
49 json_internal_vec![$($elems,)*]
50 };
51
52 (@array [$($elems:expr),*]) => {
54 json_internal_vec![$($elems),*]
55 };
56
57 (@array [$($elems:expr,)*] null $($rest:tt)*) => {
59 value_internal!(@array [$($elems,)* value_internal!(null)] $($rest)*)
60 };
61
62 (@array [$($elems:expr,)*] true $($rest:tt)*) => {
64 value_internal!(@array [$($elems,)* value_internal!(true)] $($rest)*)
65 };
66
67 (@array [$($elems:expr,)*] false $($rest:tt)*) => {
69 value_internal!(@array [$($elems,)* value_internal!(false)] $($rest)*)
70 };
71
72 (@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
74 value_internal!(@array [$($elems,)* value_internal!([$($array)*])] $($rest)*)
75 };
76
77 (@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
79 value_internal!(@array [$($elems,)* value_internal!({$($map)*})] $($rest)*)
80 };
81
82 (@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
84 value_internal!(@array [$($elems,)* value_internal!($next),] $($rest)*)
85 };
86
87 (@array [$($elems:expr,)*] $last:expr) => {
89 value_internal!(@array [$($elems,)* value_internal!($last)])
90 };
91
92 (@array [$($elems:expr),*] , $($rest:tt)*) => {
94 value_internal!(@array [$($elems,)*] $($rest)*)
95 };
96
97 (@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
99 json_unexpected!($unexpected)
100 };
101
102 (@object $object:ident () () ()) => {};
114
115 (@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
117 let _ = $object.insert(($($key)+).into(), $value);
118 value_internal!(@object $object () ($($rest)*) ($($rest)*));
119 };
120
121 (@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
123 json_unexpected!($unexpected);
124 };
125
126 (@object $object:ident [$($key:tt)+] ($value:expr)) => {
128 let _ = $object.insert(($($key)+).into(), $value);
129 };
130
131 (@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
133 value_internal!(@object $object [$($key)+] (value_internal!(null)) $($rest)*);
134 };
135
136 (@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
138 value_internal!(@object $object [$($key)+] (value_internal!(true)) $($rest)*);
139 };
140
141 (@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
143 value_internal!(@object $object [$($key)+] (value_internal!(false)) $($rest)*);
144 };
145
146 (@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
148 value_internal!(@object $object [$($key)+] (value_internal!([$($array)*])) $($rest)*);
149 };
150
151 (@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
153 value_internal!(@object $object [$($key)+] (value_internal!({$($map)*})) $($rest)*);
154 };
155
156 (@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
158 value_internal!(@object $object [$($key)+] (value_internal!($value)) , $($rest)*);
159 };
160
161 (@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
163 value_internal!(@object $object [$($key)+] (value_internal!($value)));
164 };
165
166 (@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
168 value_internal!();
170 };
171
172 (@object $object:ident ($($key:tt)+) () $copy:tt) => {
175 value_internal!();
177 };
178
179 (@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
181 json_unexpected!($colon);
183 };
184
185 (@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
187 json_unexpected!($comma);
189 };
190
191 (@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
194 value_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
195 };
196
197 (@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
199 json_expect_expr_comma!($($unexpected)+);
200 };
201
202 (@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
204 value_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
205 };
206
207 (null) => {
214 $crate::LoroValue::Null
215 };
216
217 (true) => {
218 $crate::LoroValue::Bool(true)
219 };
220
221 (false) => {
222 $crate::LoroValue::Bool(false)
223 };
224
225 ([]) => {
226 $crate::LoroValue::List(json_internal_vec![].into())
227 };
228
229 ([ $($tt:tt)+ ]) => {
230 $crate::LoroValue::List(value_internal!(@array [] $($tt)+).into())
231 };
232
233 ({}) => {
234 $crate::LoroValue::Map(Default::default())
235 };
236
237 ({ $($tt:tt)+ }) => {
238 ({
239 let mut object = $crate::FxHashMap::default();
240 value_internal!(@object object () ($($tt)+) ($($tt)+));
241 $crate::LoroValue::Map(object.into())
242 })
243 };
244
245 ($other:expr) => {
248 $crate::to_value($other)
249 };
250}
251
252#[macro_export]
253#[doc(hidden)]
254macro_rules! json_unexpected {
255 () => {};
256}
257
258#[macro_export]
262#[doc(hidden)]
263macro_rules! json_internal_vec {
264 ($($content:tt)*) => {
265 vec![$($content)*]
266 };
267}
268
269#[cfg(test)]
270mod test {
271 #[test]
272 fn test_value_macro() {
273 let v = loro_value!([1, 2, 3]);
274 let list = v.into_list().unwrap();
275 assert_eq!(&*list, &[1.into(), 2.into(), 3.into()]);
276
277 let map = loro_value!({
278 "hi": true,
279 "false": false,
280 "null": null,
281 "list": [],
282 "integer": 123,
283 "float": 123.123,
284 "map": {
285 "a": "1"
286 },
287 "binary": b"123",
288 });
289
290 let map = map.into_map().unwrap();
291 assert_eq!(map.len(), 8);
292 assert!(*map.get("hi").unwrap().as_bool().unwrap());
293 assert!(!(*map.get("false").unwrap().as_bool().unwrap()));
294 assert!(map.get("null").unwrap().is_null());
295 assert_eq!(map.get("list").unwrap().as_list().unwrap().len(), 0);
296 assert_eq!(*map.get("integer").unwrap().as_i64().unwrap(), 123);
297 assert_eq!(*map.get("float").unwrap().as_double().unwrap(), 123.123);
298 assert_eq!(map.get("map").unwrap().as_map().unwrap().len(), 1);
299 assert_eq!(
300 &**map
301 .get("map")
302 .unwrap()
303 .as_map()
304 .unwrap()
305 .get("a")
306 .unwrap()
307 .as_string()
308 .unwrap(),
309 "1"
310 );
311 assert_eq!(
312 &**map.get("binary").unwrap().as_binary().unwrap(),
313 &b"123".to_vec()
314 );
315 }
316}