1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#![forbid(unsafe_code)]
#![deny(missing_docs)]

//! This crate provides procedural macros used for the `custom-format` crate.

#[cfg(any(feature = "runtime", feature = "compile-time"))]
mod fmt;

#[cfg(any(feature = "runtime", feature = "compile-time"))]
use proc_macro::TokenStream;

/// Wrapper function for converting [`proc_macro::TokenStream`] to `proc_macro2::TokenStream` for tests
#[cfg(any(feature = "runtime", feature = "compile-time"))]
#[allow(clippy::useless_conversion)]
fn fmt(input: TokenStream, skip_first: bool, root_macro: &str, compile_time: bool) -> TokenStream {
    fmt::fmt(input.into(), skip_first, root_macro, compile_time).parse().unwrap()
}

//
// Macros for runtime format specifier checking
//

/// Constructs parameters for the other string-formatting macros
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_format_args(input: TokenStream) -> TokenStream {
    fmt(input, false, "::core::format_args!", false)
}

/// Creates a `String` using interpolation of runtime expressions
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_format(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::format!", false)
}

/// Prints to the standard output
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_print(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::print!", false)
}

/// Prints to the standard output, with a newline
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_println(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::println!", false)
}

/// Prints to the standard error
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_eprint(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::eprint!", false)
}

/// Prints to the standard error, with a newline
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_eprintln(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::eprintln!", false)
}

/// Writes formatted data into a buffer
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_write(input: TokenStream) -> TokenStream {
    fmt(input, true, "::core::write!", false)
}

/// Write formatted data into a buffer, with a newline appended
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_writeln(input: TokenStream) -> TokenStream {
    fmt(input, true, "::core::writeln!", false)
}

/// Panics the current thread
#[proc_macro]
#[cfg(feature = "runtime")]
pub fn runtime_panic(input: TokenStream) -> TokenStream {
    fmt(input, false, "::core::panic!", false)
}

//
// Macros for compile-time format specifier checking
//

/// Constructs parameters for the other string-formatting macros
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_format_args(input: TokenStream) -> TokenStream {
    fmt(input, false, "::core::format_args!", true)
}

/// Creates a `String` using interpolation of runtime expressions
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_format(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::format!", true)
}

/// Prints to the standard output
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_print(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::print!", true)
}

/// Prints to the standard output, with a newline
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_println(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::println!", true)
}

/// Prints to the standard error
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_eprint(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::eprint!", true)
}

/// Prints to the standard error, with a newline
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_eprintln(input: TokenStream) -> TokenStream {
    fmt(input, false, "::std::eprintln!", true)
}

/// Writes formatted data into a buffer
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_write(input: TokenStream) -> TokenStream {
    fmt(input, true, "::core::write!", true)
}

/// Write formatted data into a buffer, with a newline appended
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_writeln(input: TokenStream) -> TokenStream {
    fmt(input, true, "::core::writeln!", true)
}

/// Panics the current thread
#[proc_macro]
#[cfg(feature = "compile-time")]
pub fn compile_time_panic(input: TokenStream) -> TokenStream {
    fmt(input, false, "::core::panic!", true)
}