@@ -92,6 +92,9 @@ pub struct Formatter<'a> {
9292 args : & ' a [ Argument < ' a > ] ,
9393}
9494
95+ // NB. Argument is essentially an optimized partially applied formatting function,
96+ // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`.
97+
9598enum Void { }
9699
97100/// This struct represents the generic "argument" which is taken by the Xprintf
@@ -100,37 +103,66 @@ enum Void {}
100103/// types, and then this struct is used to canonicalize arguments to one type.
101104#[ experimental = "implementation detail of the `format_args!` macro" ]
102105pub struct Argument < ' a > {
103- formatter : extern "Rust" fn ( & Void , & mut Formatter ) -> Result ,
104106 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+ }
105136}
106137
107138impl < ' a > Arguments < ' a > {
108139 /// 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.
112141 #[ doc( hidden) ] #[ inline]
113142 #[ 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 > {
116145 Arguments {
117- pieces : mem :: transmute ( pieces) ,
146+ pieces : pieces,
118147 fmt : None ,
119148 args : args
120149 }
121150 }
122151
123152 /// This function is used to specify nonstandard formatting parameters.
124153 /// 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 .
126158 #[ doc( hidden) ] #[ inline]
127159 #[ 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 > {
131163 Arguments {
132- pieces : mem :: transmute ( pieces) ,
133- fmt : Some ( mem :: transmute ( fmt) ) ,
164+ pieces : pieces,
165+ fmt : Some ( fmt) ,
134166 args : args
135167 }
136168 }
@@ -312,15 +344,13 @@ impl<'a> Formatter<'a> {
312344
313345 fn getcount ( & mut self , cnt : & rt:: Count ) -> Option < uint > {
314346 match * cnt {
315- rt:: CountIs ( n) => { Some ( n) }
316- rt:: CountImplied => { None }
347+ rt:: CountIs ( n) => Some ( n) ,
348+ rt:: CountImplied => None ,
317349 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 ( )
320351 }
321352 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 ( ) )
324354 }
325355 }
326356 }
@@ -533,30 +563,17 @@ impl Show for Error {
533563/// create the Argument structures that are passed into the `format` function.
534564#[ doc( hidden) ] #[ inline]
535565#[ 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 ,
537567 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)
552569}
553570
554571/// 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.
556573#[ doc( hidden) ] #[ inline]
557574#[ experimental = "implementation detail of the `format_args!` macro" ]
558575pub fn argumentuint < ' a > ( s : & ' a uint ) -> Argument < ' a > {
559- argument ( Show :: fmt , s)
576+ Argument :: from_uint ( s)
560577}
561578
562579// Implementations of the core formatting traits
0 commit comments