@@ -1002,8 +1002,8 @@ pub mod span;
1002
1002
pub mod __macro_support {
1003
1003
pub use crate :: callsite:: { Callsite , Registration } ;
1004
1004
use crate :: { collect:: Interest , Metadata } ;
1005
- use core:: fmt;
1006
1005
use core:: sync:: atomic:: Ordering ;
1006
+ use core:: { fmt, str} ;
1007
1007
1008
1008
#[ cfg( feature = "portable-atomic" ) ]
1009
1009
use portable_atomic:: AtomicU8 ;
@@ -1014,7 +1014,7 @@ pub mod __macro_support {
1014
1014
// Re-export the `core` functions that are used in macros. This allows
1015
1015
// a crate to be named `core` and avoid name clashes.
1016
1016
// See here: https://github.com/tokio-rs/tracing/issues/2761
1017
- pub use core:: { concat, file, format_args, iter:: Iterator , line, option:: Option } ;
1017
+ pub use core:: { concat, file, format_args, iter:: Iterator , line, option:: Option , stringify } ;
1018
1018
1019
1019
/// Callsite implementation used by macro-generated code.
1020
1020
///
@@ -1202,6 +1202,66 @@ pub mod __macro_support {
1202
1202
. finish ( )
1203
1203
}
1204
1204
}
1205
+
1206
+ /// Implementation detail used for constructing FieldSet names from raw
1207
+ /// identifiers. In `info!(..., r#type = "...")` the macro would end up
1208
+ /// constructing a name equivalent to `FieldName(*b"type")`.
1209
+ pub struct FieldName < const N : usize > ( [ u8 ; N ] ) ;
1210
+
1211
+ impl < const N : usize > FieldName < N > {
1212
+ /// Convert `"prefix.r#keyword.suffix"` to `b"prefix.keyword.suffix"`.
1213
+ pub const fn new ( input : & str ) -> Self {
1214
+ let input = input. as_bytes ( ) ;
1215
+ let mut output = [ 0u8 ; N ] ;
1216
+ let mut read = 0 ;
1217
+ let mut write = 0 ;
1218
+ while read < input. len ( ) {
1219
+ if read + 1 < input. len ( ) && input[ read] == b'r' && input[ read + 1 ] == b'#' {
1220
+ read += 2 ;
1221
+ }
1222
+ output[ write] = input[ read] ;
1223
+ read += 1 ;
1224
+ write += 1 ;
1225
+ }
1226
+ assert ! ( write == N ) ;
1227
+ Self ( output)
1228
+ }
1229
+
1230
+ pub const fn as_str ( & self ) -> & str {
1231
+ // SAFETY: Because of the private visibility of self.0, it must have
1232
+ // been computed by Self::new. So these bytes are all of the bytes
1233
+ // of some original valid UTF-8 string, but with "r#" substrings
1234
+ // removed, which cannot have produced invalid UTF-8.
1235
+ unsafe { str:: from_utf8_unchecked ( self . 0 . as_slice ( ) ) }
1236
+ }
1237
+ }
1238
+
1239
+ impl FieldName < 0 > {
1240
+ /// For `"prefix.r#keyword.suffix"` compute `"prefix.keyword.suffix".len()`.
1241
+ pub const fn len ( input : & str ) -> usize {
1242
+ // Count occurrences of "r#"
1243
+ let mut raw = 0 ;
1244
+
1245
+ let mut i = 0 ;
1246
+ while i < input. len ( ) {
1247
+ if input. as_bytes ( ) [ i] == b'#' {
1248
+ raw += 1 ;
1249
+ }
1250
+ i += 1 ;
1251
+ }
1252
+
1253
+ input. len ( ) - 2 * raw
1254
+ }
1255
+ }
1256
+
1257
+ impl < const N : usize > fmt:: Debug for FieldName < N > {
1258
+ fn fmt ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1259
+ formatter
1260
+ . debug_tuple ( "FieldName" )
1261
+ . field ( & self . as_str ( ) )
1262
+ . finish ( )
1263
+ }
1264
+ }
1205
1265
}
1206
1266
1207
1267
#[ cfg( feature = "log" ) ]
0 commit comments