emit_macros/
lib.rs

1/*!
2Implementation details for `emit!` macros.
3
4This crate is not intended to be consumed directly.
5*/
6
7/*
8# Organization
9
10This crate contains the proc-macros that are exported in the `emit` crate. It expands to code that uses the `emit::__private` API, in particular the `emit::macro_hooks` module.
11
12# Hooks
13
14Code is transformed through _hooks_. A hook is a well-known method call, like `a.__private_emit_capture_as_default()`. The behavior of the hook is defined in `emit::macro_hooks`. Attribute macros look for these hooks and replace them to change behavior. For example, `#[emit::as_debug]` looks for any `__private_emit_capture_as_*` method and replaces it with `__private_emit_capture_as_debug`.
15
16# Testing
17
18Tests for this project mostly live in the top-level `test/ui` crate.
19*/
20
21#![deny(missing_docs)]
22#![doc(html_logo_url = "https://raw.githubusercontent.com/emit-rs/emit/main/asset/logo.svg")]
23
24extern crate proc_macro;
25
26#[macro_use]
27extern crate quote;
28
29#[macro_use]
30extern crate syn;
31
32use std::collections::HashMap;
33
34use proc_macro2::TokenStream;
35
36mod args;
37mod build;
38mod capture;
39mod dbg;
40mod emit;
41mod fmt;
42mod format;
43mod hook;
44mod key;
45mod optional;
46mod props;
47mod sample;
48mod span;
49mod template;
50mod util;
51
52use util::ResultToTokens;
53
54/**
55The set of hooks defined as a map.
56
57Hooks are regular attribute macros, but will be eagerly applied when expanding other macros to avoid the nightly-only feature that allows attribute macros on expressions. The `hook::eval_hooks` function will do this expansion.
58*/
59fn hooks() -> HashMap<&'static str, fn(TokenStream, TokenStream) -> syn::Result<TokenStream>> {
60    let mut map = HashMap::new();
61
62    map.insert(
63        "fmt",
64        (|args: TokenStream, expr: TokenStream| {
65            fmt::rename_hook_tokens(fmt::RenameHookTokens { args, expr })
66        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
67    );
68
69    map.insert(
70        "key",
71        (|args: TokenStream, expr: TokenStream| {
72            key::rename_hook_tokens(key::RenameHookTokens { args, expr })
73        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
74    );
75
76    map.insert(
77        "optional",
78        (|args: TokenStream, expr: TokenStream| {
79            optional::rename_hook_tokens(optional::RenameHookTokens { args, expr })
80        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
81    );
82
83    map.insert(
84        "as_value",
85        (|args: TokenStream, expr: TokenStream| {
86            capture_as(
87                "as_value",
88                args,
89                expr,
90                quote!(__private_capture_as_value),
91                quote!(__private_capture_anon_as_value),
92            )
93        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
94    );
95
96    map.insert(
97        "as_debug",
98        (|args: TokenStream, expr: TokenStream| {
99            capture_as(
100                "as_debug",
101                args,
102                expr,
103                quote!(__private_capture_as_debug),
104                quote!(__private_capture_anon_as_debug),
105            )
106        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
107    );
108
109    map.insert(
110        "as_display",
111        (|args: TokenStream, expr: TokenStream| {
112            capture_as(
113                "as_display",
114                args,
115                expr,
116                quote!(__private_capture_as_display),
117                quote!(__private_capture_anon_as_display),
118            )
119        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
120    );
121
122    map.insert(
123        "as_sval",
124        (|args: TokenStream, expr: TokenStream| {
125            #[cfg(feature = "sval")]
126            {
127                capture_as(
128                    "as_sval",
129                    args,
130                    expr,
131                    quote!(__private_capture_as_sval),
132                    quote!(__private_capture_anon_as_sval),
133                )
134            }
135            #[cfg(not(feature = "sval"))]
136            {
137                use syn::spanned::Spanned;
138
139                let _ = args;
140
141                Err(syn::Error::new(expr.span(), "capturing with `sval` is only possible when the `sval` Cargo feature is enabled"))
142            }
143        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>
144    );
145
146    map.insert(
147        "as_serde",
148        (|args: TokenStream, expr: TokenStream| {
149            #[cfg(feature = "serde")]
150            {
151                capture_as(
152                    "as_serde",
153                    args,
154                    expr,
155                    quote!(__private_capture_as_serde),
156                    quote!(__private_capture_anon_as_serde),
157                )
158            }
159            #[cfg(not(feature = "serde"))]
160            {
161                use syn::spanned::Spanned;
162
163                let _ = args;
164
165                Err(syn::Error::new(expr.span(), "capturing with `serde` is only possible when the `serde` Cargo feature is enabled"))
166            }
167        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>
168    );
169
170    map.insert(
171        "as_error",
172        (|args: TokenStream, expr: TokenStream| {
173            #[cfg(feature = "std")]
174            {
175                capture_as(
176                    "as_error",
177                    args,
178                    expr,
179                    quote!(__private_capture_as_error),
180                    quote!(__private_capture_as_error),
181                )
182            }
183            #[cfg(not(feature = "std"))]
184            {
185                use syn::spanned::Spanned;
186
187                let _ = args;
188
189                Err(syn::Error::new(
190                    expr.span(),
191                    "capturing errors is only possible when the `std` Cargo feature is enabled",
192                ))
193            }
194        }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
195    );
196
197    map
198}
199
200#[doc = "Format a template."]
201#[doc = ""]
202#[doc = include_str!("./doc_fmt.md")]
203#[proc_macro]
204pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
205    format::expand_tokens(format::ExpandTokens {
206        input: TokenStream::from(item),
207    })
208    .unwrap_or_compile_error()
209}
210
211#[doc = "Construct an event that can be emitted manually."]
212#[doc = ""]
213#[doc = include_str!("./doc_evt.md")]
214#[proc_macro]
215pub fn evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
216    build::expand_evt_tokens(build::ExpandEvtTokens {
217        level: None,
218        input: item.into(),
219    })
220    .unwrap_or_compile_error()
221}
222
223#[doc = "Construct an event at the debug level that can be emitted manually."]
224#[doc = ""]
225#[doc = include_str!("./doc_evt.md")]
226#[proc_macro]
227pub fn debug_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
228    build::expand_evt_tokens(build::ExpandEvtTokens {
229        level: Some(quote!(emit::Level::Debug)),
230        input: item.into(),
231    })
232    .unwrap_or_compile_error()
233}
234
235#[doc = "Construct an event at the info level that can be emitted manually."]
236#[doc = ""]
237#[doc = include_str!("./doc_evt.md")]
238#[proc_macro]
239pub fn info_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
240    build::expand_evt_tokens(build::ExpandEvtTokens {
241        level: Some(quote!(emit::Level::Info)),
242        input: item.into(),
243    })
244    .unwrap_or_compile_error()
245}
246
247#[doc = "Construct an event at the warn level that can be emitted manually."]
248#[doc = ""]
249#[doc = include_str!("./doc_evt.md")]
250#[proc_macro]
251pub fn warn_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
252    build::expand_evt_tokens(build::ExpandEvtTokens {
253        level: Some(quote!(emit::Level::Warn)),
254        input: item.into(),
255    })
256    .unwrap_or_compile_error()
257}
258
259#[doc = "Construct an event at the error level that can be emitted manually."]
260#[doc = ""]
261#[doc = include_str!("./doc_evt.md")]
262#[proc_macro]
263pub fn error_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
264    build::expand_evt_tokens(build::ExpandEvtTokens {
265        level: Some(quote!(emit::Level::Error)),
266        input: item.into(),
267    })
268    .unwrap_or_compile_error()
269}
270
271#[doc = "Trace the execution of a function."]
272#[doc = ""]
273#[doc = include_str!("./doc_span.md")]
274#[proc_macro_attribute]
275pub fn span(
276    args: proc_macro::TokenStream,
277    item: proc_macro::TokenStream,
278) -> proc_macro::TokenStream {
279    span::expand_tokens(span::ExpandTokens {
280        level: None,
281        input: TokenStream::from(args),
282        item: TokenStream::from(item),
283    })
284    .unwrap_or_compile_error()
285}
286
287#[doc = "Trace the execution of a function at the debug level."]
288#[doc = ""]
289#[doc = include_str!("./doc_span.md")]
290#[proc_macro_attribute]
291pub fn debug_span(
292    args: proc_macro::TokenStream,
293    item: proc_macro::TokenStream,
294) -> proc_macro::TokenStream {
295    span::expand_tokens(span::ExpandTokens {
296        level: Some(quote!(emit::Level::Debug)),
297        input: TokenStream::from(args),
298        item: TokenStream::from(item),
299    })
300    .unwrap_or_compile_error()
301}
302
303#[doc = "Trace the execution of a function at the info level."]
304#[doc = ""]
305#[doc = include_str!("./doc_span.md")]
306#[proc_macro_attribute]
307pub fn info_span(
308    args: proc_macro::TokenStream,
309    item: proc_macro::TokenStream,
310) -> proc_macro::TokenStream {
311    span::expand_tokens(span::ExpandTokens {
312        level: Some(quote!(emit::Level::Info)),
313        input: TokenStream::from(args),
314        item: TokenStream::from(item),
315    })
316    .unwrap_or_compile_error()
317}
318
319#[doc = "Trace the execution of a function at the warn level."]
320#[doc = ""]
321#[doc = include_str!("./doc_span.md")]
322#[proc_macro_attribute]
323pub fn warn_span(
324    args: proc_macro::TokenStream,
325    item: proc_macro::TokenStream,
326) -> proc_macro::TokenStream {
327    span::expand_tokens(span::ExpandTokens {
328        level: Some(quote!(emit::Level::Warn)),
329        input: TokenStream::from(args),
330        item: TokenStream::from(item),
331    })
332    .unwrap_or_compile_error()
333}
334
335#[doc = "Trace the execution of a function at the error level."]
336#[doc = ""]
337#[doc = include_str!("./doc_span.md")]
338#[proc_macro_attribute]
339pub fn error_span(
340    args: proc_macro::TokenStream,
341    item: proc_macro::TokenStream,
342) -> proc_macro::TokenStream {
343    span::expand_tokens(span::ExpandTokens {
344        level: Some(quote!(emit::Level::Error)),
345        input: TokenStream::from(args),
346        item: TokenStream::from(item),
347    })
348    .unwrap_or_compile_error()
349}
350
351#[doc = "Create a span that can be started and completed manually."]
352#[doc = ""]
353#[doc = include_str!("./doc_new_span.md")]
354#[proc_macro]
355pub fn new_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
356    span::expand_new_tokens(span::ExpandNewTokens {
357        level: None,
358        input: TokenStream::from(item),
359    })
360    .unwrap_or_compile_error()
361}
362
363#[doc = "Create a span at the debug level that can be started and completed manually."]
364#[doc = ""]
365#[doc = include_str!("./doc_new_span.md")]
366#[proc_macro]
367pub fn new_debug_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
368    span::expand_new_tokens(span::ExpandNewTokens {
369        level: Some(quote!(emit::Level::Debug)),
370        input: TokenStream::from(item),
371    })
372    .unwrap_or_compile_error()
373}
374
375#[doc = "Create a span at the info level that can be started and completed manually."]
376#[doc = ""]
377#[doc = include_str!("./doc_new_span.md")]
378#[proc_macro]
379pub fn new_info_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
380    span::expand_new_tokens(span::ExpandNewTokens {
381        level: Some(quote!(emit::Level::Info)),
382        input: TokenStream::from(item),
383    })
384    .unwrap_or_compile_error()
385}
386
387#[doc = "Create a span at the warn level that can be started and completed manually."]
388#[doc = ""]
389#[doc = include_str!("./doc_new_span.md")]
390#[proc_macro]
391pub fn new_warn_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
392    span::expand_new_tokens(span::ExpandNewTokens {
393        level: Some(quote!(emit::Level::Warn)),
394        input: TokenStream::from(item),
395    })
396    .unwrap_or_compile_error()
397}
398
399#[doc = "Create a span at the error level that can be started and completed manually."]
400#[doc = ""]
401#[doc = include_str!("./doc_new_span.md")]
402#[proc_macro]
403pub fn new_error_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
404    span::expand_new_tokens(span::ExpandNewTokens {
405        level: Some(quote!(emit::Level::Error)),
406        input: TokenStream::from(item),
407    })
408    .unwrap_or_compile_error()
409}
410
411#[doc = "Construct a template."]
412#[doc = ""]
413#[doc = include_str!("./doc_tpl.md")]
414#[proc_macro]
415pub fn tpl(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
416    build::expand_tpl_tokens(build::ExpandTplTokens {
417        input: TokenStream::from(item),
418    })
419    .unwrap_or_compile_error()
420}
421
422#[doc = "Emit an event."]
423#[doc = ""]
424#[doc = include_str!("./doc_emit.md")]
425#[proc_macro]
426pub fn emit(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
427    emit::expand_tokens(emit::ExpandTokens {
428        level: None,
429        input: TokenStream::from(item),
430    })
431    .unwrap_or_compile_error()
432}
433
434#[doc = "Emit an event at the debug level."]
435#[doc = ""]
436#[doc = include_str!("./doc_emit.md")]
437#[proc_macro]
438pub fn debug(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
439    emit::expand_tokens(emit::ExpandTokens {
440        level: Some(quote!(emit::Level::Debug)),
441        input: TokenStream::from(item),
442    })
443    .unwrap_or_compile_error()
444}
445
446#[doc = "Emit an event at the info level."]
447#[doc = ""]
448#[doc = include_str!("./doc_emit.md")]
449#[proc_macro]
450pub fn info(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
451    emit::expand_tokens(emit::ExpandTokens {
452        level: Some(quote!(emit::Level::Info)),
453        input: TokenStream::from(item),
454    })
455    .unwrap_or_compile_error()
456}
457
458#[doc = "Emit an event at the warn level."]
459#[doc = ""]
460#[doc = include_str!("./doc_emit.md")]
461#[proc_macro]
462pub fn warn(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
463    emit::expand_tokens(emit::ExpandTokens {
464        level: Some(quote!(emit::Level::Warn)),
465        input: TokenStream::from(item),
466    })
467    .unwrap_or_compile_error()
468}
469
470#[doc = "Emit an event at the error level."]
471#[doc = ""]
472#[doc = include_str!("./doc_emit.md")]
473#[proc_macro]
474pub fn error(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
475    emit::expand_tokens(emit::ExpandTokens {
476        level: Some(quote!(emit::Level::Error)),
477        input: TokenStream::from(item),
478    })
479    .unwrap_or_compile_error()
480}
481
482#[doc = "Emit a temporary event as a quick-and-dirty debugging aid."]
483#[doc = ""]
484#[doc = include_str!("./doc_dbg.md")]
485#[proc_macro]
486pub fn dbg(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
487    dbg::expand_tokens(dbg::ExpandTokens {
488        input: TokenStream::from(item),
489    })
490    .unwrap_or_compile_error()
491}
492
493/**
494Emit a metric sample.
495
496# Examples
497
498Emit a metric sample from a value:
499
500```ignore
501let my_metric = 42;
502
503emit::sample!(value: my_metric);
504```
505
506In the above example, the `name` is inferred to be `"my_metric"` using the name of the identifier in the `value` control parameter.
507
508The `name` can also be specified manually, and is required if `value` is not an identifier:
509
510```ignore
511emit::sample!(name: "my_metric", value: 42);
512```
513
514Properties can be attached to metric samples:
515
516```ignore
517let my_metric = 42;
518
519let metric = emit::sample!(value: my_metric, props: emit::props! { my_property: "some value" });
520```
521*/
522#[doc = ""]
523#[doc = include_str!("./doc_sample.md")]
524#[proc_macro]
525pub fn sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
526    sample::expand_tokens(sample::ExpandTokens {
527        agg: None,
528        input: TokenStream::from(item),
529    })
530    .unwrap_or_compile_error()
531}
532
533/**
534Emit a metric sample with `count` as its aggregation.
535
536# Examples
537
538See [`macro@sample`].
539*/
540#[doc = ""]
541#[doc = include_str!("./doc_sample.md")]
542#[proc_macro]
543pub fn count_sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
544    sample::expand_tokens(sample::ExpandTokens {
545        agg: Some({
546            let agg = emit_core::well_known::METRIC_AGG_COUNT;
547
548            quote!(#agg)
549        }),
550        input: TokenStream::from(item),
551    })
552    .unwrap_or_compile_error()
553}
554
555/**
556Emit a metric sample with `sum` as its aggregation.
557
558# Examples
559
560See [`macro@sample`].
561*/
562#[doc = ""]
563#[doc = include_str!("./doc_sample.md")]
564#[proc_macro]
565pub fn sum_sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
566    sample::expand_tokens(sample::ExpandTokens {
567        agg: Some({
568            let agg = emit_core::well_known::METRIC_AGG_SUM;
569
570            quote!(#agg)
571        }),
572        input: TokenStream::from(item),
573    })
574    .unwrap_or_compile_error()
575}
576
577/**
578Emit a metric sample with `min` as its aggregation.
579
580# Examples
581
582See [`macro@sample`].
583*/
584#[doc = ""]
585#[doc = include_str!("./doc_sample.md")]
586#[proc_macro]
587pub fn min_sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
588    sample::expand_tokens(sample::ExpandTokens {
589        agg: Some({
590            let agg = emit_core::well_known::METRIC_AGG_MIN;
591
592            quote!(#agg)
593        }),
594        input: TokenStream::from(item),
595    })
596    .unwrap_or_compile_error()
597}
598
599/**
600Emit a metric sample with `max` as its aggregation.
601
602# Examples
603
604See [`macro@sample`].
605*/
606#[doc = ""]
607#[doc = include_str!("./doc_sample.md")]
608#[proc_macro]
609pub fn max_sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
610    sample::expand_tokens(sample::ExpandTokens {
611        agg: Some({
612            let agg = emit_core::well_known::METRIC_AGG_MAX;
613
614            quote!(#agg)
615        }),
616        input: TokenStream::from(item),
617    })
618    .unwrap_or_compile_error()
619}
620
621/**
622Emit a metric sample with `last` as its aggregation.
623
624# Examples
625
626See [`macro@sample`].
627*/
628#[doc = ""]
629#[doc = include_str!("./doc_sample.md")]
630#[proc_macro]
631pub fn last_sample(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
632    sample::expand_tokens(sample::ExpandTokens {
633        agg: Some({
634            let agg = emit_core::well_known::METRIC_AGG_LAST;
635
636            quote!(#agg)
637        }),
638        input: TokenStream::from(item),
639    })
640    .unwrap_or_compile_error()
641}
642
643/**
644Construct a metric sample.
645
646# Examples
647
648Construct a metric sample from a value:
649
650```ignore
651let my_metric = 42;
652
653let metric = emit::metric!(value: my_metric);
654```
655
656In the above example, the `name` is inferred to be `"my_metric"` using the name of the identifier in the `value` control parameter.
657
658The `name` can also be specified manually, and is required if `value` is not an identifier:
659
660```ignore
661let metric = emit::metric!(name: "my_metric", value: 42);
662```
663
664Properties can be attached to metric samples:
665
666```ignore
667let my_metric = 42;
668
669let metric = emit::metric!(value: my_metric, props: emit::props! { my_property: "some value" });
670```
671*/
672#[doc = ""]
673#[doc = include_str!("./doc_metric.md")]
674#[proc_macro]
675pub fn metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
676    sample::expand_metric_tokens(sample::ExpandTokens {
677        agg: None,
678        input: TokenStream::from(item),
679    })
680    .unwrap_or_compile_error()
681}
682
683/**
684Construct a metric sample with `count` as its aggregation.
685
686# Examples
687
688See [`macro@metric`].
689*/
690#[doc = ""]
691#[doc = include_str!("./doc_metric.md")]
692#[proc_macro]
693pub fn count_metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
694    sample::expand_metric_tokens(sample::ExpandTokens {
695        agg: Some({
696            let agg = emit_core::well_known::METRIC_AGG_COUNT;
697
698            quote!(#agg)
699        }),
700        input: TokenStream::from(item),
701    })
702    .unwrap_or_compile_error()
703}
704
705/**
706Construct a metric sample with `sum` as its aggregation.
707
708# Examples
709
710See [`macro@metric`].
711*/
712#[doc = ""]
713#[doc = include_str!("./doc_metric.md")]
714#[proc_macro]
715pub fn sum_metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
716    sample::expand_metric_tokens(sample::ExpandTokens {
717        agg: Some({
718            let agg = emit_core::well_known::METRIC_AGG_SUM;
719
720            quote!(#agg)
721        }),
722        input: TokenStream::from(item),
723    })
724    .unwrap_or_compile_error()
725}
726
727/**
728Construct a metric sample with `min` as its aggregation.
729
730# Examples
731
732See [`macro@metric`].
733*/
734#[doc = ""]
735#[doc = include_str!("./doc_metric.md")]
736#[proc_macro]
737pub fn min_metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
738    sample::expand_metric_tokens(sample::ExpandTokens {
739        agg: Some({
740            let agg = emit_core::well_known::METRIC_AGG_MIN;
741
742            quote!(#agg)
743        }),
744        input: TokenStream::from(item),
745    })
746    .unwrap_or_compile_error()
747}
748
749/**
750Construct a metric sample with `max` as its aggregation.
751
752# Examples
753
754See [`macro@metric`].
755*/
756#[doc = ""]
757#[doc = include_str!("./doc_metric.md")]
758#[proc_macro]
759pub fn max_metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
760    sample::expand_metric_tokens(sample::ExpandTokens {
761        agg: Some({
762            let agg = emit_core::well_known::METRIC_AGG_MAX;
763
764            quote!(#agg)
765        }),
766        input: TokenStream::from(item),
767    })
768    .unwrap_or_compile_error()
769}
770
771/**
772Construct a metric sample with `last` as its aggregation.
773
774# Examples
775
776See [`macro@metric`].
777*/
778#[doc = ""]
779#[doc = include_str!("./doc_metric.md")]
780#[proc_macro]
781pub fn last_metric(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
782    sample::expand_metric_tokens(sample::ExpandTokens {
783        agg: Some({
784            let agg = emit_core::well_known::METRIC_AGG_LAST;
785
786            quote!(#agg)
787        }),
788        input: TokenStream::from(item),
789    })
790    .unwrap_or_compile_error()
791}
792
793/**
794Construct a path.
795
796# Syntax
797
798```text
799path
800```
801
802where
803
804- `path`: A string literal containing a valid `emit` path.
805
806# Returns
807
808An `emit::Path`.
809*/
810#[proc_macro]
811pub fn path(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
812    build::expand_path_tokens(build::ExpandPathTokens {
813        input: TokenStream::from(item),
814    })
815    .unwrap_or_compile_error()
816}
817
818/**
819Construct a set of properties.
820
821# Syntax
822
823```text
824(property),*
825```
826
827where
828
829- `property`: A Rust field-value for a property. The identifier of the field-value is the key of the property.
830
831# Returns
832
833An `impl emit::Props`.
834*/
835#[proc_macro]
836pub fn props(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
837    build::expand_props_tokens(build::ExpandPropsTokens {
838        input: TokenStream::from(item),
839    })
840    .unwrap_or_compile_error()
841}
842
843/**
844Specify Rust format flags to use when rendering a property in a template.
845
846# Syntax
847
848```text
849fmt_string
850```
851
852where
853
854- `fmt_string`: A string literal with the format flags, like `":?"`. See the [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html) docs for details on available flags.
855
856# Applicable to
857
858This attribute can be applied to properties that appear in a template.
859*/
860#[proc_macro_attribute]
861pub fn fmt(
862    args: proc_macro::TokenStream,
863    item: proc_macro::TokenStream,
864) -> proc_macro::TokenStream {
865    (hook::get("fmt").unwrap())(TokenStream::from(args), TokenStream::from(item))
866        .unwrap_or_compile_error()
867}
868
869/**
870Specify the key for a property.
871
872# Syntax
873
874```text
875key
876```
877
878where
879
880- `key`: A string literal with the key to use. The key doesn't need to be a valid Rust identifier.
881
882# Applicable to
883
884This attribute can be applied to properties.
885*/
886#[proc_macro_attribute]
887pub fn key(
888    args: proc_macro::TokenStream,
889    item: proc_macro::TokenStream,
890) -> proc_macro::TokenStream {
891    (hook::get("key").unwrap())(TokenStream::from(args), TokenStream::from(item))
892        .unwrap_or_compile_error()
893}
894
895/**
896Specify that a property value of `None` should not be captured, instead of being captured as `null`.
897
898# Syntax
899
900This macro doesn't accept any arguments.
901
902# Applicable to
903
904This attribute can be applied to properties where the type is `Option<&T>`.
905*/
906#[proc_macro_attribute]
907pub fn optional(
908    args: proc_macro::TokenStream,
909    item: proc_macro::TokenStream,
910) -> proc_macro::TokenStream {
911    (hook::get("optional").unwrap())(TokenStream::from(args), TokenStream::from(item))
912        .unwrap_or_compile_error()
913}
914
915/**
916Capture a property using its `ToValue` implementation.
917
918# Syntax
919
920This macro doesn't accept any arguments.
921
922# Applicable to
923
924This attribute can be applied to properties.
925*/
926#[proc_macro_attribute]
927pub fn as_value(
928    args: proc_macro::TokenStream,
929    item: proc_macro::TokenStream,
930) -> proc_macro::TokenStream {
931    (hook::get("as_value").unwrap())(TokenStream::from(args), TokenStream::from(item))
932        .unwrap_or_compile_error()
933}
934
935/**
936Capture a property using its `Debug` implementation.
937
938# Syntax
939
940This macro doesn't accept any arguments.
941
942# Applicable to
943
944This attribute can be applied to properties.
945*/
946#[proc_macro_attribute]
947pub fn as_debug(
948    args: proc_macro::TokenStream,
949    item: proc_macro::TokenStream,
950) -> proc_macro::TokenStream {
951    (hook::get("as_debug").unwrap())(TokenStream::from(args), TokenStream::from(item))
952        .unwrap_or_compile_error()
953}
954
955/**
956Capture a property using its `Display` implementation.
957
958# Syntax
959
960This macro doesn't accept any arguments.
961
962# Applicable to
963
964This attribute can be applied to properties.
965*/
966#[proc_macro_attribute]
967pub fn as_display(
968    args: proc_macro::TokenStream,
969    item: proc_macro::TokenStream,
970) -> proc_macro::TokenStream {
971    (hook::get("as_display").unwrap())(TokenStream::from(args), TokenStream::from(item))
972        .unwrap_or_compile_error()
973}
974
975/**
976Capture a property using its `sval::Value` implementation.
977
978# Syntax
979
980This macro doesn't accept any arguments.
981
982# Applicable to
983
984This attribute can be applied to properties.
985*/
986#[proc_macro_attribute]
987pub fn as_sval(
988    args: proc_macro::TokenStream,
989    item: proc_macro::TokenStream,
990) -> proc_macro::TokenStream {
991    (hook::get("as_sval").unwrap())(TokenStream::from(args), TokenStream::from(item))
992        .unwrap_or_compile_error()
993}
994
995/**
996Capture a property using its `serde::Serialize` implementation.
997
998# Syntax
999
1000This macro doesn't accept any arguments.
1001
1002# Applicable to
1003
1004This attribute can be applied to properties.
1005*/
1006#[proc_macro_attribute]
1007pub fn as_serde(
1008    args: proc_macro::TokenStream,
1009    item: proc_macro::TokenStream,
1010) -> proc_macro::TokenStream {
1011    (hook::get("as_serde").unwrap())(TokenStream::from(args), TokenStream::from(item))
1012        .unwrap_or_compile_error()
1013}
1014
1015/**
1016Capture a property using its `Error` implementation.
1017
1018# Syntax
1019
1020This macro doesn't accept any arguments.
1021
1022# Applicable to
1023
1024This attribute can be applied to properties.
1025*/
1026#[proc_macro_attribute]
1027pub fn as_error(
1028    args: proc_macro::TokenStream,
1029    item: proc_macro::TokenStream,
1030) -> proc_macro::TokenStream {
1031    (hook::get("as_error").unwrap())(TokenStream::from(args), TokenStream::from(item))
1032        .unwrap_or_compile_error()
1033}
1034
1035fn capture_as(
1036    name: &'static str,
1037    args: TokenStream,
1038    expr: TokenStream,
1039    as_fn: TokenStream,
1040    as_anon_fn: TokenStream,
1041) -> syn::Result<TokenStream> {
1042    capture::rename_hook_tokens(capture::RenameHookTokens {
1043        name,
1044        args,
1045        expr,
1046        to: |args: &capture::Args| {
1047            if args.inspect {
1048                as_fn.clone()
1049            } else {
1050                as_anon_fn.clone()
1051            }
1052        },
1053    })
1054}