1#[macro_export]
64macro_rules! value {
65 (null) => {
67 $crate::Value::NULL
68 };
69
70 (true) => {
72 $crate::Value::TRUE
73 };
74
75 (false) => {
77 $crate::Value::FALSE
78 };
79
80 ([]) => {
82 $crate::Value::from($crate::VArray::new())
83 };
84
85 ([ $($elem:tt),* $(,)? ]) => {{
87 let mut arr = $crate::VArray::new();
88 $(
89 arr.push($crate::value!($elem));
90 )*
91 $crate::Value::from(arr)
92 }};
93
94 ({}) => {
96 $crate::Value::from($crate::VObject::new())
97 };
98
99 ({ $($key:tt : $value:tt),* $(,)? }) => {{
101 let mut obj = $crate::VObject::new();
102 $(
103 obj.insert($key, $crate::value!($value));
104 )*
105 $crate::Value::from(obj)
106 }};
107
108 (( $expr:expr )) => {
110 $crate::Value::from($expr)
111 };
112
113 ($other:expr) => {
115 $crate::Value::from($other)
116 };
117}
118
119#[cfg(test)]
120mod tests {
121 use crate::{VArray, Value};
122
123 #[test]
124 fn test_null() {
125 let v = value!(null);
126 assert!(v.is_null());
127 }
128
129 #[test]
130 fn test_booleans() {
131 assert_eq!(value!(true), Value::TRUE);
132 assert_eq!(value!(false), Value::FALSE);
133 }
134
135 #[test]
136 fn test_numbers() {
137 let v = value!(42);
138 assert_eq!(v.as_number().unwrap().to_i64(), Some(42));
139
140 let v = value!(-17);
141 assert_eq!(v.as_number().unwrap().to_i64(), Some(-17));
142
143 let v = value!(1.5);
144 assert!((v.as_number().unwrap().to_f64().unwrap() - 1.5).abs() < 0.001);
145 }
146
147 #[test]
148 fn test_strings() {
149 let v = value!("hello");
150 assert_eq!(v.as_string().unwrap().as_str(), "hello");
151
152 let v = value!("hello world with spaces");
153 assert_eq!(v.as_string().unwrap().as_str(), "hello world with spaces");
154 }
155
156 #[test]
157 fn test_empty_array() {
158 let v = value!([]);
159 assert!(v.is_array());
160 assert!(v.as_array().unwrap().is_empty());
161 }
162
163 #[test]
164 fn test_array_of_numbers() {
165 let v = value!([1, 2, 3]);
166 let arr = v.as_array().unwrap();
167 assert_eq!(arr.len(), 3);
168 assert_eq!(arr[0].as_number().unwrap().to_i64(), Some(1));
169 assert_eq!(arr[1].as_number().unwrap().to_i64(), Some(2));
170 assert_eq!(arr[2].as_number().unwrap().to_i64(), Some(3));
171 }
172
173 #[test]
174 fn test_array_mixed_types() {
175 let v = value!([1, "two", true, null]);
176 let arr = v.as_array().unwrap();
177 assert_eq!(arr.len(), 4);
178 assert_eq!(arr[0].as_number().unwrap().to_i64(), Some(1));
179 assert_eq!(arr[1].as_string().unwrap().as_str(), "two");
180 assert_eq!(arr[2].as_bool(), Some(true));
181 assert!(arr[3].is_null());
182 }
183
184 #[test]
185 fn test_empty_object() {
186 let v = value!({});
187 assert!(v.is_object());
188 assert!(v.as_object().unwrap().is_empty());
189 }
190
191 #[test]
192 fn test_object_simple() {
193 let v = value!({
194 "name": "Alice",
195 "age": 30,
196 "active": true
197 });
198 let obj = v.as_object().unwrap();
199 assert_eq!(obj.len(), 3);
200 assert_eq!(obj["name"].as_string().unwrap().as_str(), "Alice");
201 assert_eq!(obj["age"].as_number().unwrap().to_i64(), Some(30));
202 assert_eq!(obj["active"].as_bool(), Some(true));
203 }
204
205 #[test]
206 fn test_nested_structure() {
207 let v = value!({
208 "users": [
209 { "name": "Alice", "age": 30 },
210 { "name": "Bob", "age": 25 }
211 ],
212 "count": 2
213 });
214
215 let obj = v.as_object().unwrap();
216 assert_eq!(obj["count"].as_number().unwrap().to_i64(), Some(2));
217
218 let users = obj["users"].as_array().unwrap();
219 assert_eq!(users.len(), 2);
220
221 let alice = users[0].as_object().unwrap();
222 assert_eq!(alice["name"].as_string().unwrap().as_str(), "Alice");
223 assert_eq!(alice["age"].as_number().unwrap().to_i64(), Some(30));
224
225 let bob = users[1].as_object().unwrap();
226 assert_eq!(bob["name"].as_string().unwrap().as_str(), "Bob");
227 assert_eq!(bob["age"].as_number().unwrap().to_i64(), Some(25));
228 }
229
230 #[test]
231 fn test_variable_interpolation() {
232 let name = "Alice";
233 let age = 30i64;
234
235 let v = value!({
236 "name": (name),
237 "age": (age)
238 });
239
240 let obj = v.as_object().unwrap();
241 assert_eq!(obj["name"].as_string().unwrap().as_str(), "Alice");
242 assert_eq!(obj["age"].as_number().unwrap().to_i64(), Some(30));
243 }
244
245 #[test]
246 fn test_array_interpolation() {
247 let items = vec![1i64, 2, 3];
248 let arr: VArray = items.into_iter().collect();
249
250 let v = value!({
251 "items": (arr)
252 });
253
254 let obj = v.as_object().unwrap();
255 assert_eq!(obj["items"].as_array().unwrap().len(), 3);
256 }
257
258 #[test]
259 fn test_trailing_comma() {
260 let v = value!([1, 2, 3,]);
262 assert_eq!(v.as_array().unwrap().len(), 3);
263
264 let v = value!({
266 "a": 1,
267 "b": 2,
268 });
269 assert_eq!(v.as_object().unwrap().len(), 2);
270 }
271
272 #[test]
273 fn test_deeply_nested() {
274 let v = value!({
275 "level1": {
276 "level2": {
277 "level3": {
278 "data": [1, 2, 3]
279 }
280 }
281 }
282 });
283
284 let data = &v.as_object().unwrap()["level1"].as_object().unwrap()["level2"]
285 .as_object()
286 .unwrap()["level3"]
287 .as_object()
288 .unwrap()["data"];
289
290 assert_eq!(data.as_array().unwrap().len(), 3);
291 }
292}