const_format_proc_macros/
lib.rs

1#![allow(clippy::or_fun_call)]
2#![allow(clippy::derive_partial_eq_without_eq)]
3
4use proc_macro::TokenStream as TokenStream1;
5
6use proc_macro2::TokenStream as TokenStream2;
7
8#[cfg(feature = "derive")]
9#[macro_use]
10mod macros;
11
12#[cfg(feature = "derive")]
13mod datastructure;
14
15mod error;
16
17#[cfg(feature = "derive")]
18mod derive_debug;
19
20mod format_args;
21
22mod format_str;
23
24mod format_macro;
25
26mod formatting;
27
28mod parse_utils;
29
30mod respan_to_macro;
31
32mod shared_arg_parsing;
33
34mod spanned;
35
36mod utils;
37
38#[cfg(test)]
39mod test_utils;
40
41use crate::error::Error;
42use crate::parse_utils::MyParse;
43
44fn compile_err_empty_str(e: crate::Error) -> TokenStream2 {
45    let e = e.to_compile_error();
46    quote::quote!({
47        #e;
48        ""
49    })
50}
51
52#[doc(hidden)]
53#[proc_macro]
54pub fn __concatcp_impl(input: TokenStream1) -> TokenStream1 {
55    MyParse::parse_token_stream_1(input)
56        .and_then(format_macro::concatcp_impl)
57        .unwrap_or_else(compile_err_empty_str)
58        .into()
59}
60
61/// Input syntax: `"format string", (arg0), (name = arg1)` (with optional trailing comma).
62///
63/// The arguments are parenthesized to not require syn to parse `arg0` and `arg1` as syn::Expr,
64/// they're just parsed as a `TokenStream2`.
65///
66/// They're guaranteed to be expressions when this macro is invoked by `const_format` macros,
67/// which should be the only ones to do so.
68#[doc(hidden)]
69#[proc_macro]
70pub fn __formatcp_impl(input: TokenStream1) -> TokenStream1 {
71    MyParse::parse_token_stream_1(input)
72        .and_then(format_macro::formatcp_impl)
73        .unwrap_or_else(compile_err_empty_str)
74        .into()
75}
76
77#[doc(hidden)]
78#[proc_macro]
79pub fn __formatc_impl(input: TokenStream1) -> TokenStream1 {
80    MyParse::parse_token_stream_1(input)
81        .and_then(format_macro::formatc_macro_impl)
82        .unwrap_or_else(compile_err_empty_str)
83        .into()
84}
85
86#[doc(hidden)]
87#[proc_macro]
88pub fn __formatc_if_impl(input: TokenStream1) -> TokenStream1 {
89    MyParse::parse_token_stream_1(input)
90        .and_then(format_macro::formatc_if_macro_impl)
91        .unwrap_or_else(compile_err_empty_str)
92        .into()
93}
94
95#[doc(hidden)]
96#[proc_macro]
97pub fn __formatcp_if_impl(input: TokenStream1) -> TokenStream1 {
98    MyParse::parse_token_stream_1(input)
99        .and_then(format_macro::formatcp_if_macro_impl)
100        .unwrap_or_else(compile_err_empty_str)
101        .into()
102}
103
104#[doc(hidden)]
105#[proc_macro]
106pub fn __writec_impl(input: TokenStream1) -> TokenStream1 {
107    MyParse::parse_token_stream_1(input)
108        .and_then(format_macro::writec_macro_impl)
109        .unwrap_or_else(|e| {
110            let e = e.to_compile_error();
111            quote::quote!({
112                #e;
113                ::core::result::Result::Ok(())
114            })
115        })
116        .into()
117}
118
119#[cfg(feature = "derive")]
120#[proc_macro_derive(ConstDebug, attributes(cdeb))]
121pub fn derive_const_debug(input: TokenStream1) -> TokenStream1 {
122    syn::parse(input)
123        .map_err(crate::Error::from)
124        .and_then(derive_debug::derive_constdebug_impl)
125        .unwrap_or_else(|e| e.to_compile_error())
126        .into()
127}
128
129/// `__respan_to!(( foo tokens )  bar tokens )`
130/// Respan all the bar tokens to the span of the foo tokens
131#[proc_macro]
132pub fn respan_to(input: TokenStream1) -> TokenStream1 {
133    crate::respan_to_macro::implementation(input.into()).into()
134}