@@ -212,3 +212,212 @@ macro_rules! doc {
212
212
object
213
213
} } ;
214
214
}
215
+
216
+ /// Construct a [`crate::RawBson`] value from a literal.
217
+ ///
218
+ /// ```rust
219
+ /// use bson::rawbson;
220
+ ///
221
+ /// let value = rawbson!({
222
+ /// "code": 200,
223
+ /// "success": true,
224
+ /// "payload": {
225
+ /// "some": [
226
+ /// "pay",
227
+ /// "loads",
228
+ /// ]
229
+ /// }
230
+ /// });
231
+ /// ```
232
+ #[ macro_export]
233
+ macro_rules! rawbson {
234
+ //////////////////////////////////////////////////////////////////////////
235
+ // TT muncher for parsing the inside of an array [...]. Produces a
236
+ // RawArrayBuf containing the elements.
237
+ //
238
+ // Must be invoked as: bson!(@array [] $($tt)*)
239
+ //////////////////////////////////////////////////////////////////////////
240
+
241
+ // Finished with trailing comma.
242
+ ( @array [ $( $elems: expr, ) * ] ) => {
243
+ <$crate:: RawArrayBuf as std:: iter:: FromIterator :: <$crate:: RawBson >>:: from_iter( vec![ $( $elems, ) * ] )
244
+ } ;
245
+
246
+ // Finished without trailing comma.
247
+ ( @array [ $( $elems: expr) ,* ] ) => {
248
+ <$crate:: RawArrayBuf as std:: iter:: FromIterator :: <$crate:: RawBson >>:: from_iter( vec![ $( $elems) ,* ] )
249
+ } ;
250
+
251
+ // Next element is `null`.
252
+ ( @array [ $( $elems: expr, ) * ] null $( $rest: tt) * ) => {
253
+ $crate:: rawbson!( @array [ $( $elems, ) * $crate:: rawbson!( null) ] $( $rest) * )
254
+ } ;
255
+
256
+ // Next element is an array.
257
+ ( @array [ $( $elems: expr, ) * ] [ $( $array: tt) * ] $( $rest: tt) * ) => {
258
+ $crate:: rawbson!( @array [ $( $elems, ) * $crate:: rawbson!( [ $( $array) * ] ) ] $( $rest) * )
259
+ } ;
260
+
261
+ // Next element is a map.
262
+ ( @array [ $( $elems: expr, ) * ] { $( $map: tt) * } $( $rest: tt) * ) => {
263
+ $crate:: rawbson!( @array [ $( $elems, ) * $crate:: rawbson!( { $( $map) * } ) ] $( $rest) * )
264
+ } ;
265
+
266
+ // Next element is an expression followed by comma.
267
+ ( @array [ $( $elems: expr, ) * ] $next: expr, $( $rest: tt) * ) => {
268
+ $crate:: rawbson!( @array [ $( $elems, ) * $crate:: rawbson!( $next) , ] $( $rest) * )
269
+ } ;
270
+
271
+ // Last element is an expression with no trailing comma.
272
+ ( @array [ $( $elems: expr, ) * ] $last: expr) => {
273
+ $crate:: rawbson!( @array [ $( $elems, ) * $crate:: rawbson!( $last) ] )
274
+ } ;
275
+
276
+ // Comma after the most recent element.
277
+ ( @array [ $( $elems: expr) ,* ] , $( $rest: tt) * ) => {
278
+ $crate:: rawbson!( @array [ $( $elems, ) * ] $( $rest) * )
279
+ } ;
280
+
281
+ //////////////////////////////////////////////////////////////////////////
282
+ // TT muncher for parsing the inside of an object {...}. Each entry is
283
+ // inserted into the given map variable.
284
+ //
285
+ // Must be invoked as: rawbson!(@object $map () ($($tt)*) ($($tt)*))
286
+ //
287
+ // We require two copies of the input tokens so that we can match on one
288
+ // copy and trigger errors on the other copy.
289
+ //////////////////////////////////////////////////////////////////////////
290
+
291
+ // Finished.
292
+ ( @object $object: ident ( ) ( ) ( ) ) => { } ;
293
+
294
+ // Insert the current entry followed by trailing comma.
295
+ ( @object $object: ident [ $( $key: tt) +] ( $value: expr) , $( $rest: tt) * ) => {
296
+ $object. append( ( $( $key) +) , $value) ;
297
+ $crate:: rawbson!( @object $object ( ) ( $( $rest) * ) ( $( $rest) * ) ) ;
298
+ } ;
299
+
300
+ // Insert the last entry without trailing comma.
301
+ ( @object $object: ident [ $( $key: tt) +] ( $value: expr) ) => {
302
+ $object. append( ( $( $key) +) , $value) ;
303
+ } ;
304
+
305
+ // Next value is `null`.
306
+ ( @object $object: ident ( $( $key: tt) +) ( : null $( $rest: tt) * ) $copy: tt) => {
307
+ $crate:: rawbson!( @object $object [ $( $key) +] ( $crate:: rawbson!( null) ) $( $rest) * ) ;
308
+ } ;
309
+
310
+ // Next value is an array.
311
+ ( @object $object: ident ( $( $key: tt) +) ( : [ $( $array: tt) * ] $( $rest: tt) * ) $copy: tt) => {
312
+ $crate:: rawbson!( @object $object [ $( $key) +] ( $crate:: rawbson!( [ $( $array) * ] ) ) $( $rest) * ) ;
313
+ } ;
314
+
315
+ // Next value is a map.
316
+ ( @object $object: ident ( $( $key: tt) +) ( : { $( $map: tt) * } $( $rest: tt) * ) $copy: tt) => {
317
+ $crate:: rawbson!( @object $object [ $( $key) +] ( $crate:: rawbson!( { $( $map) * } ) ) $( $rest) * ) ;
318
+ } ;
319
+
320
+ // Next value is an expression followed by comma.
321
+ ( @object $object: ident ( $( $key: tt) +) ( : $value: expr , $( $rest: tt) * ) $copy: tt) => {
322
+ $crate:: rawbson!( @object $object [ $( $key) +] ( $crate:: rawbson!( $value) ) , $( $rest) * ) ;
323
+ } ;
324
+
325
+ // Last value is an expression with no trailing comma.
326
+ ( @object $object: ident ( $( $key: tt) +) ( : $value: expr) $copy: tt) => {
327
+ $crate:: rawbson!( @object $object [ $( $key) +] ( $crate:: rawbson!( $value) ) ) ;
328
+ } ;
329
+
330
+ // Missing value for last entry. Trigger a reasonable error message.
331
+ ( @object $object: ident ( $( $key: tt) +) ( : ) $copy: tt) => {
332
+ // "unexpected end of macro invocation"
333
+ $crate:: rawbson!( ) ;
334
+ } ;
335
+
336
+ // Missing key-value separator and value for last entry.
337
+ // Trigger a reasonable error message.
338
+ ( @object $object: ident ( $( $key: tt) +) ( ) $copy: tt) => {
339
+ // "unexpected end of macro invocation"
340
+ $crate:: rawbson!( ) ;
341
+ } ;
342
+
343
+ // Misplaced key-value separator. Trigger a reasonable error message.
344
+ ( @object $object: ident ( ) ( : $( $rest: tt) * ) ( $kv_separator: tt $( $copy: tt) * ) ) => {
345
+ // Takes no arguments so "no rules expected the token `:`".
346
+ unimplemented!( $kv_separator) ;
347
+ } ;
348
+
349
+ // Found a comma inside a key. Trigger a reasonable error message.
350
+ ( @object $object: ident ( $( $key: tt) * ) ( , $( $rest: tt) * ) ( $comma: tt $( $copy: tt) * ) ) => {
351
+ // Takes no arguments so "no rules expected the token `,`".
352
+ unimplemented!( $comma) ;
353
+ } ;
354
+
355
+ // Key is fully parenthesized. This avoids clippy double_parens false
356
+ // positives because the parenthesization may be necessary here.
357
+ ( @object $object: ident ( ) ( ( $key: expr) : $( $rest: tt) * ) $copy: tt) => {
358
+ $crate:: rawbson!( @object $object ( $key) ( : $( $rest) * ) ( : $( $rest) * ) ) ;
359
+ } ;
360
+
361
+ // Munch a token into the current key.
362
+ ( @object $object: ident ( $( $key: tt) * ) ( $tt: tt $( $rest: tt) * ) $copy: tt) => {
363
+ $crate:: rawbson!( @object $object ( $( $key) * $tt) ( $( $rest) * ) ( $( $rest) * ) ) ;
364
+ } ;
365
+
366
+ //////////////////////////////////////////////////////////////////////////
367
+ // The main implementation.
368
+ //
369
+ // Must be invoked as: rawbson!($($bson)+)
370
+ //////////////////////////////////////////////////////////////////////////
371
+
372
+ ( null) => {
373
+ $crate:: RawBson :: Null
374
+ } ;
375
+
376
+ ( [ ] ) => {
377
+ $crate:: RawBson :: Array ( $crate:: RawArrayBuf :: new( ) )
378
+ } ;
379
+
380
+ ( [ $( $tt: tt) + ] ) => {
381
+ $crate:: RawBson :: Array ( $crate:: rawbson!( @array [ ] $( $tt) +) )
382
+ } ;
383
+
384
+ ( { } ) => {
385
+ $crate:: RawBson :: Document ( $crate:: rawdoc!{ } )
386
+ } ;
387
+
388
+ ( { $( $tt: tt) +} ) => {
389
+ $crate:: RawBson :: Document ( $crate:: rawdoc!{ $( $tt) +} )
390
+ } ;
391
+
392
+ // Any Into<RawBson> type.
393
+ // Must be below every other rule.
394
+ ( $other: expr) => {
395
+ $crate:: RawBson :: from( $other)
396
+ } ;
397
+ }
398
+
399
+ /// Construct a [`crate::RawDocumentBuf`] value.
400
+ ///
401
+ /// ```rust
402
+ /// use bson::rawdoc;
403
+ ///
404
+ /// let value = rawdoc! {
405
+ /// "code": 200,
406
+ /// "success": true,
407
+ /// "payload": {
408
+ /// "some": [
409
+ /// "pay",
410
+ /// "loads",
411
+ /// ]
412
+ /// }
413
+ /// };
414
+ /// ```
415
+ #[ macro_export]
416
+ macro_rules! rawdoc {
417
+ ( ) => { { $crate:: RawDocumentBuf :: new( ) } } ;
418
+ ( $( $tt: tt) + ) => { {
419
+ let mut object = $crate:: RawDocumentBuf :: new( ) ;
420
+ $crate:: rawbson!( @object object ( ) ( $( $tt) +) ( $( $tt) +) ) ;
421
+ object
422
+ } } ;
423
+ }
0 commit comments