@@ -7,9 +7,11 @@ use crate::char::EscapeDebugExtArgs;
7
7
use crate :: iter;
8
8
use crate :: marker:: PhantomData ;
9
9
use crate :: mem;
10
- use crate :: num:: fmt as numfmt;
10
+ use crate :: num:: { fmt as numfmt, NonZeroUsize } ;
11
11
use crate :: ops:: Deref ;
12
+ use crate :: ptr;
12
13
use crate :: result;
14
+ use crate :: slice;
13
15
use crate :: str;
14
16
15
17
mod builders;
@@ -277,15 +279,43 @@ impl<'a> Formatter<'a> {
277
279
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
278
280
#[ derive( Copy , Clone ) ]
279
281
pub struct Arguments < ' a > {
280
- // Format string pieces to print.
281
- pieces : & ' a [ & ' static str ] ,
282
+ /// The number of string pieces and place holders combined.
283
+ ///
284
+ /// For example:
285
+ /// - 1 for `format_args!("abc")`
286
+ /// - 2 for `format_args!("abc{}")`
287
+ /// - 3 for `format_args!("abc{}xyz")`
288
+ /// - 4 for `format_args!("abc{}xyz{}")`
289
+ /// - 5 for `format_args!("abc{}xyz{}123")`
290
+ ///
291
+ /// The first part is always a string piece, but it may be an empty string.
292
+ /// E.g. format_args!("{}") has two parts, one empty string piece and one placeholder.
293
+ ///
294
+ /// The number of placeholders is `num_parts / 2`.
295
+ /// The number of string pieces is `(num_parts + 1) / 2`.
296
+ num_parts : NonZeroUsize ,
282
297
283
- // Placeholder specs, or `None` if all specs are default (as in "{}{}").
284
- fmt : Option < & ' a [ rt:: Placeholder ] > ,
298
+ /// The string pieces and the placeholders.
299
+ ///
300
+ /// If `num_parts` is one, this stores the &'static str directly.
301
+ /// Otherwise, it stores pointers to both the slice of string pieces and the slice of placeholders.
302
+ ///
303
+ /// The length of those slices are determined by the `num_parts` field above.
304
+ parts : Parts ,
285
305
286
- // Dynamic arguments for interpolation, to be interleaved with string
287
- // pieces. (Every argument is preceded by a string piece.)
288
- args : & ' a [ rt:: Argument < ' a > ] ,
306
+ /// Pointer to the start of the array of arguments.
307
+ args : * const rt:: Argument < ' a > ,
308
+ }
309
+
310
+ #[ derive( Copy , Clone ) ]
311
+ union Parts {
312
+ /// Used if `num_parts == 1`.
313
+ string : & ' static str ,
314
+ /// Used if `num_parts > 1`.
315
+ ///
316
+ /// The placaeholders pointer can be null for default placeholders:
317
+ /// a placeholder for each argument once, in order, with default formatting options.
318
+ strings_and_placeholders : ( * const & ' static str , * const rt:: Placeholder ) ,
289
319
}
290
320
291
321
/// Used by the format_args!() macro to create a fmt::Arguments object.
@@ -294,38 +324,60 @@ pub struct Arguments<'a> {
294
324
impl < ' a > Arguments < ' a > {
295
325
#[ inline]
296
326
#[ rustc_const_unstable( feature = "const_fmt_arguments_new" , issue = "none" ) ]
297
- pub const fn new_const ( pieces : & ' a [ & ' static str ] ) -> Self {
298
- if pieces. len ( ) > 1 {
299
- panic ! ( "invalid args" ) ;
327
+ #[ cfg( bootstrap) ]
328
+ pub const fn new_const ( strings : & ' a [ & ' static str ] ) -> Self {
329
+ match strings {
330
+ [ ] => Self :: new_str ( "" ) ,
331
+ [ s] => Self :: new_str ( s) ,
332
+ _ => panic ! ( "invalid args" ) ,
300
333
}
301
- Arguments { pieces, fmt : None , args : & [ ] }
334
+ }
335
+
336
+ #[ inline]
337
+ #[ rustc_const_unstable( feature = "const_fmt_arguments_new" , issue = "none" ) ]
338
+ pub const fn new_str ( s : & ' static str ) -> Self {
339
+ Self { num_parts : NonZeroUsize :: MIN , parts : Parts { string : s } , args : ptr:: null ( ) }
302
340
}
303
341
304
342
/// When using the format_args!() macro, this function is used to generate the
305
343
/// Arguments structure.
306
344
#[ inline]
307
- pub fn new_v1 ( pieces : & ' a [ & ' static str ] , args : & ' a [ rt:: Argument < ' a > ] ) -> Arguments < ' a > {
308
- if pieces. len ( ) < args. len ( ) || pieces. len ( ) > args. len ( ) + 1 {
309
- panic ! ( "invalid args" ) ;
345
+ pub fn new_v1 ( strings : & ' a [ & ' static str ] , args : & ' a [ rt:: Argument < ' a > ] ) -> Self {
346
+ // The number of strings and args should be the same,
347
+ // except there may be one additional string after the last arg.
348
+ assert ! ( strings. len( ) == args. len( ) || strings. len( ) == args. len( ) + 1 , "invalid args" ) ;
349
+ match NonZeroUsize :: new ( strings. len ( ) + args. len ( ) ) {
350
+ None => Self :: new_str ( "" ) ,
351
+ Some ( NonZeroUsize :: MIN ) => Self :: new_str ( strings[ 0 ] ) ,
352
+ Some ( num_parts) => Self {
353
+ num_parts,
354
+ parts : Parts { strings_and_placeholders : ( strings. as_ptr ( ) , ptr:: null ( ) ) } ,
355
+ args : args. as_ptr ( ) ,
356
+ } ,
310
357
}
311
- Arguments { pieces, fmt : None , args }
312
358
}
313
359
314
360
/// This function is used to specify nonstandard formatting parameters.
315
361
///
316
362
/// An `rt::UnsafeArg` is required because the following invariants must be held
317
363
/// in order for this function to be safe:
318
- /// 1. The `pieces` slice must be at least as long as `fmt`.
319
- /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
320
- /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
364
+ /// 1. `placeholders` must be nonempty.
365
+ /// 2. The `strings` slice must be at least as long as `placeholders`.
366
+ /// 3. Every `rt::Placeholder::position` value within `placeholders` must be a valid index of `args`.
367
+ /// 4. Every `rt::Count::Param` within `placeholders` must contain a valid index of `args`.
321
368
#[ inline]
322
369
pub fn new_v1_formatted (
323
- pieces : & ' a [ & ' static str ] ,
370
+ strings : & ' a [ & ' static str ] ,
324
371
args : & ' a [ rt:: Argument < ' a > ] ,
325
- fmt : & ' a [ rt:: Placeholder ] ,
372
+ placeholders : & ' a [ rt:: Placeholder ] ,
326
373
_unsafe_arg : rt:: UnsafeArg ,
327
- ) -> Arguments < ' a > {
328
- Arguments { pieces, fmt : Some ( fmt) , args }
374
+ ) -> Self {
375
+ Self {
376
+ // SAFETY: The caller must guarantee `placeholders` is nonempty.
377
+ num_parts : unsafe { NonZeroUsize :: new_unchecked ( strings. len ( ) + placeholders. len ( ) ) } ,
378
+ parts : Parts { strings_and_placeholders : ( strings. as_ptr ( ) , placeholders. as_ptr ( ) ) } ,
379
+ args : args. as_ptr ( ) ,
380
+ }
329
381
}
330
382
331
383
/// Estimates the length of the formatted text.
@@ -334,22 +386,37 @@ impl<'a> Arguments<'a> {
334
386
/// when using `format!`. Note: this is neither the lower nor upper bound.
335
387
#[ inline]
336
388
pub fn estimated_capacity ( & self ) -> usize {
337
- let pieces_length: usize = self . pieces . iter ( ) . map ( |x| x. len ( ) ) . sum ( ) ;
338
-
339
- if self . args . is_empty ( ) {
340
- pieces_length
341
- } else if !self . pieces . is_empty ( ) && self . pieces [ 0 ] . is_empty ( ) && pieces_length < 16 {
342
- // If the format string starts with an argument,
343
- // don't preallocate anything, unless length
344
- // of pieces is significant.
345
- 0
389
+ let num_parts = self . num_parts . get ( ) ;
390
+
391
+ if num_parts == 1 {
392
+ // SAFETY: With num_parts == 1, the `parts` field stores just the string.
393
+ unsafe { self . parts . string } . len ( )
346
394
} else {
347
- // There are some arguments, so any additional push
348
- // will reallocate the string. To avoid that,
349
- // we're "pre-doubling" the capacity here.
350
- pieces_length. checked_mul ( 2 ) . unwrap_or ( 0 )
395
+ // SAFETY: With num_parts > 1, the `parts` field stores the pointers to the strings and
396
+ // placeholder slices.
397
+ let strings = unsafe {
398
+ slice:: from_raw_parts ( self . parts . strings_and_placeholders . 0 , ( num_parts + 1 ) / 2 )
399
+ } ;
400
+ let strings_length: usize = strings. iter ( ) . map ( |s| s. len ( ) ) . sum ( ) ;
401
+ if strings[ 0 ] . is_empty ( ) && strings_length < 16 {
402
+ // If the format string starts with an argument,
403
+ // don't preallocate anything, unless length
404
+ // of strings is significant.
405
+ 0
406
+ } else {
407
+ // There are some arguments, so any additional push
408
+ // will reallocate the string. To avoid that,
409
+ // we're "pre-doubling" the capacity here.
410
+ strings_length. checked_mul ( 2 ) . unwrap_or ( 0 )
411
+ }
351
412
}
352
413
}
414
+
415
+ #[ inline( always) ]
416
+ unsafe fn arg ( & self , n : usize ) -> & rt:: Argument < ' a > {
417
+ // SAFETY: Caller needs to privde a valid index.
418
+ unsafe { & * self . args . add ( n) }
419
+ }
353
420
}
354
421
355
422
impl < ' a > Arguments < ' a > {
@@ -400,10 +467,11 @@ impl<'a> Arguments<'a> {
400
467
#[ must_use]
401
468
#[ inline]
402
469
pub const fn as_str ( & self ) -> Option < & ' static str > {
403
- match ( self . pieces , self . args ) {
404
- ( [ ] , [ ] ) => Some ( "" ) ,
405
- ( [ s] , [ ] ) => Some ( s) ,
406
- _ => None ,
470
+ if self . num_parts . get ( ) == 1 {
471
+ // SAFETY: With num_parts == 1, the `parts` field stores just the string.
472
+ Some ( unsafe { self . parts . string } )
473
+ } else {
474
+ None
407
475
}
408
476
}
409
477
}
@@ -1077,80 +1145,70 @@ pub trait UpperExp {
1077
1145
///
1078
1146
/// [`write!`]: crate::write!
1079
1147
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1080
- pub fn write ( output : & mut dyn Write , args : Arguments < ' _ > ) -> Result {
1148
+ pub fn write ( output : & mut dyn Write , fmt : Arguments < ' _ > ) -> Result {
1081
1149
let mut formatter = Formatter :: new ( output) ;
1082
- let mut idx = 0 ;
1083
-
1084
- match args. fmt {
1085
- None => {
1086
- // We can use default formatting parameters for all arguments.
1087
- for ( i, arg) in args. args . iter ( ) . enumerate ( ) {
1088
- // SAFETY: args.args and args.pieces come from the same Arguments,
1089
- // which guarantees the indexes are always within bounds.
1090
- let piece = unsafe { args. pieces . get_unchecked ( i) } ;
1091
- if !piece. is_empty ( ) {
1092
- formatter. buf . write_str ( * piece) ?;
1093
- }
1094
- arg. fmt ( & mut formatter) ?;
1095
- idx += 1 ;
1150
+
1151
+ if let Some ( s) = fmt. as_str ( ) {
1152
+ return formatter. buf . write_str ( s) ;
1153
+ }
1154
+
1155
+ // SAFETY: Since as_str() returned None, we know that `fmt.parts` contains the
1156
+ // strings and placeholders pointers.
1157
+ let ( strings, placeholders) = unsafe { fmt. parts . strings_and_placeholders } ;
1158
+
1159
+ // Iterate over all parts (string, placeholder, string, ...).
1160
+ // Even numbered parts are strings, odd numbered parts are placeholders.
1161
+ for i in 0 ..fmt. num_parts . get ( ) {
1162
+ if i % 2 == 0 {
1163
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds.
1164
+ let string = unsafe { & * strings. add ( i / 2 ) } ;
1165
+ if !string. is_empty ( ) {
1166
+ formatter. buf . write_str ( string) ?;
1096
1167
}
1097
- }
1098
- Some ( fmt) => {
1099
- // Every spec has a corresponding argument that is preceded by
1100
- // a string piece.
1101
- for ( i, arg) in fmt. iter ( ) . enumerate ( ) {
1102
- // SAFETY: fmt and args.pieces come from the same Arguments,
1103
- // which guarantees the indexes are always within bounds.
1104
- let piece = unsafe { args. pieces . get_unchecked ( i) } ;
1105
- if !piece. is_empty ( ) {
1106
- formatter. buf . write_str ( * piece) ?;
1107
- }
1108
- // SAFETY: arg and args.args come from the same Arguments,
1109
- // which guarantees the indexes are always within bounds.
1110
- unsafe { run ( & mut formatter, arg, args. args ) } ?;
1111
- idx += 1 ;
1168
+ } else {
1169
+ if placeholders. is_null ( ) {
1170
+ // Use default placeholders: each argument once, in order, with default formatting.
1171
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds.
1172
+ unsafe { fmt. arg ( i / 2 ) } . fmt ( & mut formatter) ?;
1173
+ } else {
1174
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds.
1175
+ unsafe { run ( & mut formatter, & fmt, & * placeholders. add ( i / 2 ) ) } ?;
1112
1176
}
1113
1177
}
1114
1178
}
1115
1179
1116
- // There can be only one trailing string piece left.
1117
- if let Some ( piece) = args. pieces . get ( idx) {
1118
- formatter. buf . write_str ( * piece) ?;
1119
- }
1120
-
1121
1180
Ok ( ( ) )
1122
1181
}
1123
1182
1124
- unsafe fn run ( fmt : & mut Formatter < ' _ > , arg : & rt:: Placeholder , args : & [ rt:: Argument < ' _ > ] ) -> Result {
1125
- fmt. fill = arg. fill ;
1126
- fmt. align = arg. align ;
1127
- fmt. flags = arg. flags ;
1128
- // SAFETY: arg and args come from the same Arguments,
1129
- // which guarantees the indexes are always within bounds.
1183
+ unsafe fn run (
1184
+ out : & mut Formatter < ' _ > ,
1185
+ fmt : & Arguments < ' _ > ,
1186
+ placeholder : & rt:: Placeholder ,
1187
+ ) -> Result {
1188
+ out. fill = placeholder. fill ;
1189
+ out. align = placeholder. align ;
1190
+ out. flags = placeholder. flags ;
1191
+
1192
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds.
1130
1193
unsafe {
1131
- fmt . width = getcount ( args , & arg . width ) ;
1132
- fmt . precision = getcount ( args , & arg . precision ) ;
1194
+ out . width = getcount ( fmt , & placeholder . width ) ;
1195
+ out . precision = getcount ( fmt , & placeholder . precision ) ;
1133
1196
}
1134
1197
1135
- // Extract the correct argument
1136
- debug_assert ! ( arg. position < args. len( ) ) ;
1137
- // SAFETY: arg and args come from the same Arguments,
1138
- // which guarantees its index is always within bounds.
1139
- let value = unsafe { args. get_unchecked ( arg. position ) } ;
1198
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds.
1199
+ let arg = unsafe { fmt. arg ( placeholder. position ) } ;
1140
1200
1141
- // Then actually do some printing
1142
- value. fmt ( fmt)
1201
+ arg. fmt ( out)
1143
1202
}
1144
1203
1145
- unsafe fn getcount ( args : & [ rt :: Argument < ' _ > ] , cnt : & rt:: Count ) -> Option < usize > {
1204
+ unsafe fn getcount ( fmt : & Arguments < ' _ > , cnt : & rt:: Count ) -> Option < usize > {
1146
1205
match * cnt {
1147
1206
rt:: Count :: Is ( n) => Some ( n) ,
1148
1207
rt:: Count :: Implied => None ,
1149
1208
rt:: Count :: Param ( i) => {
1150
- debug_assert ! ( i < args. len( ) ) ;
1151
- // SAFETY: cnt and args come from the same Arguments,
1152
- // which guarantees this index is always within bounds.
1153
- unsafe { args. get_unchecked ( i) . as_usize ( ) }
1209
+ // SAFETY: The Arguments type guarantees the indexes are always within bounds,
1210
+ // and the caller must give a `Count` from this same `Arguments` object.
1211
+ unsafe { fmt. arg ( i) . as_usize ( ) }
1154
1212
}
1155
1213
}
1156
1214
}
0 commit comments