@@ -92,6 +92,9 @@ pub struct Formatter<'a> {
92
92
args : & ' a [ Argument < ' a > ] ,
93
93
}
94
94
95
+ // NB. Argument is essentially an optimized partially applied formatting function,
96
+ // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`.
97
+
95
98
enum Void { }
96
99
97
100
/// This struct represents the generic "argument" which is taken by the Xprintf
@@ -100,37 +103,66 @@ enum Void {}
100
103
/// types, and then this struct is used to canonicalize arguments to one type.
101
104
#[ experimental = "implementation detail of the `format_args!` macro" ]
102
105
pub struct Argument < ' a > {
103
- formatter : extern "Rust" fn ( & Void , & mut Formatter ) -> Result ,
104
106
value : & ' a Void ,
107
+ formatter : fn ( & Void , & mut Formatter ) -> Result ,
108
+ }
109
+
110
+ impl < ' a > Argument < ' a > {
111
+ #[ inline( never) ]
112
+ fn show_uint ( x : & uint , f : & mut Formatter ) -> Result {
113
+ Show :: fmt ( x, f)
114
+ }
115
+
116
+ fn new < ' a , T > ( x : & ' a T , f : fn ( & T , & mut Formatter ) -> Result ) -> Argument < ' a > {
117
+ unsafe {
118
+ Argument {
119
+ formatter : mem:: transmute ( f) ,
120
+ value : mem:: transmute ( x)
121
+ }
122
+ }
123
+ }
124
+
125
+ fn from_uint < ' a > ( x : & ' a uint ) -> Argument < ' a > {
126
+ Argument :: new ( x, Argument :: show_uint)
127
+ }
128
+
129
+ fn as_uint ( & self ) -> Option < uint > {
130
+ if self . formatter as uint == Argument :: show_uint as uint {
131
+ Some ( unsafe { * ( self . value as * const _ as * const uint ) } )
132
+ } else {
133
+ None
134
+ }
135
+ }
105
136
}
106
137
107
138
impl < ' a > Arguments < ' a > {
108
139
/// When using the format_args!() macro, this function is used to generate the
109
- /// Arguments structure. The compiler inserts an `unsafe` block to call this,
110
- /// which is valid because the compiler performs all necessary validation to
111
- /// ensure that the resulting call to format/write would be safe.
140
+ /// Arguments structure.
112
141
#[ doc( hidden) ] #[ inline]
113
142
#[ experimental = "implementation detail of the `format_args!` macro" ]
114
- pub unsafe fn new < ' a > ( pieces : & ' static [ & ' static str ] ,
115
- args : & ' a [ Argument < ' a > ] ) -> Arguments < ' a > {
143
+ pub fn new < ' a > ( pieces : & ' a [ & ' a str ] ,
144
+ args : & ' a [ Argument < ' a > ] ) -> Arguments < ' a > {
116
145
Arguments {
117
- pieces : mem :: transmute ( pieces) ,
146
+ pieces : pieces,
118
147
fmt : None ,
119
148
args : args
120
149
}
121
150
}
122
151
123
152
/// This function is used to specify nonstandard formatting parameters.
124
153
/// The `pieces` array must be at least as long as `fmt` to construct
125
- /// a valid Arguments structure.
154
+ /// a valid Arguments structure. Also, any `Count` within `fmt` that is
155
+ /// `CountIsParam` or `CountIsNextParam` has to point to an argument
156
+ /// created with `argumentuint`. However, failing to do so doesn't cause
157
+ /// unsafety, but will ignore invalid .
126
158
#[ doc( hidden) ] #[ inline]
127
159
#[ experimental = "implementation detail of the `format_args!` macro" ]
128
- pub unsafe fn with_placeholders < ' a > ( pieces : & ' static [ & ' static str ] ,
129
- fmt : & ' static [ rt:: Argument < ' static > ] ,
130
- args : & ' a [ Argument < ' a > ] ) -> Arguments < ' a > {
160
+ pub fn with_placeholders < ' a > ( pieces : & ' a [ & ' a str ] ,
161
+ fmt : & ' a [ rt:: Argument < ' a > ] ,
162
+ args : & ' a [ Argument < ' a > ] ) -> Arguments < ' a > {
131
163
Arguments {
132
- pieces : mem :: transmute ( pieces) ,
133
- fmt : Some ( mem :: transmute ( fmt) ) ,
164
+ pieces : pieces,
165
+ fmt : Some ( fmt) ,
134
166
args : args
135
167
}
136
168
}
@@ -312,15 +344,13 @@ impl<'a> Formatter<'a> {
312
344
313
345
fn getcount ( & mut self , cnt : & rt:: Count ) -> Option < uint > {
314
346
match * cnt {
315
- rt:: CountIs ( n) => { Some ( n) }
316
- rt:: CountImplied => { None }
347
+ rt:: CountIs ( n) => Some ( n) ,
348
+ rt:: CountImplied => None ,
317
349
rt:: CountIsParam ( i) => {
318
- let v = self . args [ i] . value ;
319
- unsafe { Some ( * ( v as * const _ as * const uint ) ) }
350
+ self . args [ i] . as_uint ( )
320
351
}
321
352
rt:: CountIsNextParam => {
322
- let v = self . curarg . next ( ) . unwrap ( ) . value ;
323
- unsafe { Some ( * ( v as * const _ as * const uint ) ) }
353
+ self . curarg . next ( ) . and_then ( |arg| arg. as_uint ( ) )
324
354
}
325
355
}
326
356
}
@@ -533,30 +563,17 @@ impl Show for Error {
533
563
/// create the Argument structures that are passed into the `format` function.
534
564
#[ doc( hidden) ] #[ inline]
535
565
#[ experimental = "implementation detail of the `format_args!` macro" ]
536
- pub fn argument < ' a , T > ( f : extern "Rust" fn ( & T , & mut Formatter ) -> Result ,
566
+ pub fn argument < ' a , T > ( f : fn ( & T , & mut Formatter ) -> Result ,
537
567
t : & ' a T ) -> Argument < ' a > {
538
- unsafe {
539
- Argument {
540
- formatter : mem:: transmute ( f) ,
541
- value : mem:: transmute ( t)
542
- }
543
- }
544
- }
545
-
546
- /// When the compiler determines that the type of an argument *must* be a string
547
- /// (such as for select), then it invokes this method.
548
- #[ doc( hidden) ] #[ inline]
549
- #[ experimental = "implementation detail of the `format_args!` macro" ]
550
- pub fn argumentstr < ' a > ( s : & ' a & str ) -> Argument < ' a > {
551
- argument ( Show :: fmt, s)
568
+ Argument :: new ( t, f)
552
569
}
553
570
554
571
/// When the compiler determines that the type of an argument *must* be a uint
555
- /// (such as for plural ), then it invokes this method.
572
+ /// (such as for width and precision ), then it invokes this method.
556
573
#[ doc( hidden) ] #[ inline]
557
574
#[ experimental = "implementation detail of the `format_args!` macro" ]
558
575
pub fn argumentuint < ' a > ( s : & ' a uint ) -> Argument < ' a > {
559
- argument ( Show :: fmt , s)
576
+ Argument :: from_uint ( s)
560
577
}
561
578
562
579
// Implementations of the core formatting traits
0 commit comments