]>
Commit | Line | Data |
---|---|---|
9346a6ac | 1 | // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Utilities for formatting and printing strings | |
12 | ||
85aaf69f | 13 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 14 | |
e9174d1e | 15 | use prelude::v1::*; |
9346a6ac | 16 | |
85aaf69f | 17 | use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; |
9346a6ac | 18 | use marker::PhantomData; |
1a4d82fc | 19 | use mem; |
d9579d0f | 20 | use num::flt2dec; |
9346a6ac | 21 | use ops::Deref; |
1a4d82fc | 22 | use result; |
1a4d82fc | 23 | use slice; |
9346a6ac | 24 | use str; |
85aaf69f | 25 | use self::rt::v1::Alignment; |
1a4d82fc | 26 | |
92a42be0 | 27 | #[unstable(feature = "fmt_radix", issue = "27728")] |
1a4d82fc | 28 | pub use self::num::radix; |
92a42be0 | 29 | #[unstable(feature = "fmt_radix", issue = "27728")] |
1a4d82fc | 30 | pub use self::num::Radix; |
92a42be0 | 31 | #[unstable(feature = "fmt_radix", issue = "27728")] |
1a4d82fc | 32 | pub use self::num::RadixFmt; |
92a42be0 | 33 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
34 | pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; |
35 | ||
1a4d82fc | 36 | mod num; |
c34b1796 | 37 | mod builders; |
1a4d82fc | 38 | |
e9174d1e SL |
39 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
40 | issue = "0")] | |
85aaf69f SL |
41 | #[doc(hidden)] |
42 | pub mod rt { | |
43 | pub mod v1; | |
44 | } | |
45 | ||
46 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
47 | /// The type returned by formatter methods. |
48 | pub type Result = result::Result<(), Error>; | |
49 | ||
50 | /// The error type which is returned from formatting a message into a stream. | |
51 | /// | |
52 | /// This type does not support transmission of an error other than that an error | |
53 | /// occurred. Any extra information must be arranged to be transmitted through | |
54 | /// some other means. | |
85aaf69f | 55 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 56 | #[derive(Copy, Clone, Debug)] |
1a4d82fc JJ |
57 | pub struct Error; |
58 | ||
59 | /// A collection of methods that are required to format a message into a stream. | |
60 | /// | |
61 | /// This trait is the type which this modules requires when formatting | |
85aaf69f | 62 | /// information. This is similar to the standard library's `io::Write` trait, |
1a4d82fc JJ |
63 | /// but it is only intended for use in libcore. |
64 | /// | |
65 | /// This trait should generally not be implemented by consumers of the standard | |
85aaf69f SL |
66 | /// library. The `write!` macro accepts an instance of `io::Write`, and the |
67 | /// `io::Write` trait is favored over implementing this trait. | |
68 | #[stable(feature = "rust1", since = "1.0.0")] | |
69 | pub trait Write { | |
1a4d82fc JJ |
70 | /// Writes a slice of bytes into this writer, returning whether the write |
71 | /// succeeded. | |
72 | /// | |
73 | /// This method can only succeed if the entire byte slice was successfully | |
74 | /// written, and this method will not return until all data has been | |
75 | /// written or an error occurs. | |
76 | /// | |
77 | /// # Errors | |
78 | /// | |
62682a34 | 79 | /// This function will return an instance of `Error` on error. |
85aaf69f | 80 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
81 | fn write_str(&mut self, s: &str) -> Result; |
82 | ||
d9579d0f AL |
83 | /// Writes a `char` into this writer, returning whether the write succeeded. |
84 | /// | |
85 | /// A single `char` may be encoded as more than one byte. | |
86 | /// This method can only succeed if the entire byte sequence was successfully | |
87 | /// written, and this method will not return until all data has been | |
88 | /// written or an error occurs. | |
89 | /// | |
90 | /// # Errors | |
91 | /// | |
62682a34 | 92 | /// This function will return an instance of `Error` on error. |
d9579d0f AL |
93 | #[stable(feature = "fmt_write_char", since = "1.1.0")] |
94 | fn write_char(&mut self, c: char) -> Result { | |
95 | let mut utf_8 = [0u8; 4]; | |
96 | let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0); | |
e9174d1e | 97 | self.write_str(unsafe { str::from_utf8_unchecked(&utf_8[..bytes_written]) }) |
d9579d0f AL |
98 | } |
99 | ||
b039eaaf | 100 | /// Glue for usage of the `write!` macro with implementors of this trait. |
1a4d82fc JJ |
101 | /// |
102 | /// This method should generally not be invoked manually, but rather through | |
103 | /// the `write!` macro itself. | |
85aaf69f | 104 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
105 | fn write_fmt(&mut self, args: Arguments) -> Result { |
106 | // This Adapter is needed to allow `self` (of type `&mut | |
85aaf69f | 107 | // Self`) to be cast to a Write (below) without |
1a4d82fc JJ |
108 | // requiring a `Sized` bound. |
109 | struct Adapter<'a,T: ?Sized +'a>(&'a mut T); | |
110 | ||
85aaf69f SL |
111 | impl<'a, T: ?Sized> Write for Adapter<'a, T> |
112 | where T: Write | |
1a4d82fc JJ |
113 | { |
114 | fn write_str(&mut self, s: &str) -> Result { | |
115 | self.0.write_str(s) | |
116 | } | |
117 | ||
118 | fn write_fmt(&mut self, args: Arguments) -> Result { | |
119 | self.0.write_fmt(args) | |
120 | } | |
121 | } | |
122 | ||
123 | write(&mut Adapter(self), args) | |
124 | } | |
125 | } | |
126 | ||
e9174d1e SL |
127 | #[stable(feature = "fmt_write_blanket_impl", since = "1.4.0")] |
128 | impl<'a, W: Write + ?Sized> Write for &'a mut W { | |
129 | fn write_str(&mut self, s: &str) -> Result { | |
130 | (**self).write_str(s) | |
131 | } | |
132 | ||
133 | fn write_char(&mut self, c: char) -> Result { | |
134 | (**self).write_char(c) | |
135 | } | |
136 | ||
137 | fn write_fmt(&mut self, args: Arguments) -> Result { | |
138 | (**self).write_fmt(args) | |
139 | } | |
140 | } | |
141 | ||
1a4d82fc JJ |
142 | /// A struct to represent both where to emit formatting strings to and how they |
143 | /// should be formatted. A mutable version of this is passed to all formatting | |
144 | /// traits. | |
85aaf69f | 145 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 146 | pub struct Formatter<'a> { |
c34b1796 | 147 | flags: u32, |
1a4d82fc | 148 | fill: char, |
85aaf69f | 149 | align: rt::v1::Alignment, |
c34b1796 AL |
150 | width: Option<usize>, |
151 | precision: Option<usize>, | |
1a4d82fc | 152 | |
85aaf69f SL |
153 | buf: &'a mut (Write+'a), |
154 | curarg: slice::Iter<'a, ArgumentV1<'a>>, | |
155 | args: &'a [ArgumentV1<'a>], | |
1a4d82fc JJ |
156 | } |
157 | ||
158 | // NB. Argument is essentially an optimized partially applied formatting function, | |
159 | // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`. | |
160 | ||
161 | enum Void {} | |
162 | ||
163 | /// This struct represents the generic "argument" which is taken by the Xprintf | |
164 | /// family of functions. It contains a function to format the given value. At | |
165 | /// compile time it is ensured that the function and the value have the correct | |
166 | /// types, and then this struct is used to canonicalize arguments to one type. | |
1a4d82fc | 167 | #[derive(Copy)] |
e9174d1e SL |
168 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
169 | issue = "0")] | |
85aaf69f SL |
170 | #[doc(hidden)] |
171 | pub struct ArgumentV1<'a> { | |
1a4d82fc JJ |
172 | value: &'a Void, |
173 | formatter: fn(&Void, &mut Formatter) -> Result, | |
174 | } | |
175 | ||
92a42be0 SL |
176 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
177 | issue = "0")] | |
c34b1796 AL |
178 | impl<'a> Clone for ArgumentV1<'a> { |
179 | fn clone(&self) -> ArgumentV1<'a> { | |
180 | *self | |
181 | } | |
182 | } | |
183 | ||
85aaf69f | 184 | impl<'a> ArgumentV1<'a> { |
1a4d82fc | 185 | #[inline(never)] |
c34b1796 | 186 | fn show_usize(x: &usize, f: &mut Formatter) -> Result { |
85aaf69f | 187 | Display::fmt(x, f) |
1a4d82fc JJ |
188 | } |
189 | ||
85aaf69f | 190 | #[doc(hidden)] |
e9174d1e SL |
191 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
192 | issue = "0")] | |
85aaf69f SL |
193 | pub fn new<'b, T>(x: &'b T, |
194 | f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { | |
1a4d82fc | 195 | unsafe { |
85aaf69f | 196 | ArgumentV1 { |
1a4d82fc JJ |
197 | formatter: mem::transmute(f), |
198 | value: mem::transmute(x) | |
199 | } | |
200 | } | |
201 | } | |
202 | ||
85aaf69f | 203 | #[doc(hidden)] |
e9174d1e SL |
204 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
205 | issue = "0")] | |
c34b1796 AL |
206 | pub fn from_usize(x: &usize) -> ArgumentV1 { |
207 | ArgumentV1::new(x, ArgumentV1::show_usize) | |
1a4d82fc JJ |
208 | } |
209 | ||
c34b1796 AL |
210 | fn as_usize(&self) -> Option<usize> { |
211 | if self.formatter as usize == ArgumentV1::show_usize as usize { | |
212 | Some(unsafe { *(self.value as *const _ as *const usize) }) | |
1a4d82fc JJ |
213 | } else { |
214 | None | |
215 | } | |
216 | } | |
217 | } | |
218 | ||
85aaf69f | 219 | // flags available in the v1 format of format_args |
c34b1796 | 220 | #[derive(Copy, Clone)] |
85aaf69f SL |
221 | #[allow(dead_code)] // SignMinus isn't currently used |
222 | enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } | |
223 | ||
1a4d82fc JJ |
224 | impl<'a> Arguments<'a> { |
225 | /// When using the format_args!() macro, this function is used to generate the | |
226 | /// Arguments structure. | |
227 | #[doc(hidden)] #[inline] | |
e9174d1e SL |
228 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
229 | issue = "0")] | |
85aaf69f SL |
230 | pub fn new_v1(pieces: &'a [&'a str], |
231 | args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { | |
1a4d82fc JJ |
232 | Arguments { |
233 | pieces: pieces, | |
234 | fmt: None, | |
235 | args: args | |
236 | } | |
237 | } | |
238 | ||
239 | /// This function is used to specify nonstandard formatting parameters. | |
240 | /// The `pieces` array must be at least as long as `fmt` to construct | |
241 | /// a valid Arguments structure. Also, any `Count` within `fmt` that is | |
242 | /// `CountIsParam` or `CountIsNextParam` has to point to an argument | |
c34b1796 | 243 | /// created with `argumentusize`. However, failing to do so doesn't cause |
1a4d82fc JJ |
244 | /// unsafety, but will ignore invalid . |
245 | #[doc(hidden)] #[inline] | |
e9174d1e SL |
246 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
247 | issue = "0")] | |
85aaf69f SL |
248 | pub fn new_v1_formatted(pieces: &'a [&'a str], |
249 | args: &'a [ArgumentV1<'a>], | |
250 | fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { | |
1a4d82fc JJ |
251 | Arguments { |
252 | pieces: pieces, | |
253 | fmt: Some(fmt), | |
254 | args: args | |
255 | } | |
256 | } | |
257 | } | |
258 | ||
259 | /// This structure represents a safely precompiled version of a format string | |
260 | /// and its arguments. This cannot be generated at runtime because it cannot | |
261 | /// safely be done so, so no constructors are given and the fields are private | |
262 | /// to prevent modification. | |
263 | /// | |
264 | /// The `format_args!` macro will safely create an instance of this structure | |
265 | /// and pass it to a function or closure, passed as the first argument. The | |
266 | /// macro validates the format string at compile-time so usage of the `write` | |
267 | /// and `format` functions can be safely performed. | |
85aaf69f | 268 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 269 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
270 | pub struct Arguments<'a> { |
271 | // Format string pieces to print. | |
272 | pieces: &'a [&'a str], | |
273 | ||
274 | // Placeholder specs, or `None` if all specs are default (as in "{}{}"). | |
85aaf69f | 275 | fmt: Option<&'a [rt::v1::Argument]>, |
1a4d82fc JJ |
276 | |
277 | // Dynamic arguments for interpolation, to be interleaved with string | |
278 | // pieces. (Every argument is preceded by a string piece.) | |
85aaf69f | 279 | args: &'a [ArgumentV1<'a>], |
1a4d82fc JJ |
280 | } |
281 | ||
85aaf69f SL |
282 | #[stable(feature = "rust1", since = "1.0.0")] |
283 | impl<'a> Debug for Arguments<'a> { | |
1a4d82fc | 284 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
85aaf69f | 285 | Display::fmt(self, fmt) |
1a4d82fc JJ |
286 | } |
287 | } | |
288 | ||
85aaf69f SL |
289 | #[stable(feature = "rust1", since = "1.0.0")] |
290 | impl<'a> Display for Arguments<'a> { | |
1a4d82fc JJ |
291 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
292 | write(fmt.buf, *self) | |
293 | } | |
294 | } | |
295 | ||
c1a9b12d SL |
296 | /// Format trait for the `?` character. |
297 | /// | |
298 | /// `Debug` should format the output in a programmer-facing, debugging context. | |
62682a34 SL |
299 | /// |
300 | /// Generally speaking, you should just `derive` a `Debug` implementation. | |
301 | /// | |
c1a9b12d SL |
302 | /// When used with the alternate format specifier `#?`, the output is pretty-printed. |
303 | /// | |
304 | /// For more information on formatters, see [the module-level documentation][module]. | |
305 | /// | |
b039eaaf | 306 | /// [module]: ../../std/fmt/index.html |
c1a9b12d | 307 | /// |
92a42be0 SL |
308 | /// This trait can be used with `#[derive]`. |
309 | /// | |
62682a34 SL |
310 | /// # Examples |
311 | /// | |
312 | /// Deriving an implementation: | |
313 | /// | |
314 | /// ``` | |
315 | /// #[derive(Debug)] | |
316 | /// struct Point { | |
317 | /// x: i32, | |
318 | /// y: i32, | |
319 | /// } | |
320 | /// | |
321 | /// let origin = Point { x: 0, y: 0 }; | |
322 | /// | |
323 | /// println!("The origin is: {:?}", origin); | |
324 | /// ``` | |
325 | /// | |
326 | /// Manually implementing: | |
327 | /// | |
328 | /// ``` | |
329 | /// use std::fmt; | |
330 | /// | |
331 | /// struct Point { | |
332 | /// x: i32, | |
333 | /// y: i32, | |
334 | /// } | |
335 | /// | |
336 | /// impl fmt::Debug for Point { | |
337 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
92a42be0 | 338 | /// write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) |
62682a34 SL |
339 | /// } |
340 | /// } | |
341 | /// | |
342 | /// let origin = Point { x: 0, y: 0 }; | |
343 | /// | |
344 | /// println!("The origin is: {:?}", origin); | |
345 | /// ``` | |
346 | /// | |
c1a9b12d SL |
347 | /// This outputs: |
348 | /// | |
349 | /// ```text | |
350 | /// The origin is: Point { x: 0, y: 0 } | |
351 | /// ``` | |
352 | /// | |
62682a34 SL |
353 | /// There are a number of `debug_*` methods on `Formatter` to help you with manual |
354 | /// implementations, such as [`debug_struct`][debug_struct]. | |
355 | /// | |
c1a9b12d SL |
356 | /// `Debug` implementations using either `derive` or the debug builder API |
357 | /// on `Formatter` support pretty printing using the alternate flag: `{:#?}`. | |
358 | /// | |
62682a34 | 359 | /// [debug_struct]: ../std/fmt/struct.Formatter.html#method.debug_struct |
c1a9b12d SL |
360 | /// |
361 | /// Pretty printing with `#?`: | |
362 | /// | |
363 | /// ``` | |
364 | /// #[derive(Debug)] | |
365 | /// struct Point { | |
366 | /// x: i32, | |
367 | /// y: i32, | |
368 | /// } | |
369 | /// | |
370 | /// let origin = Point { x: 0, y: 0 }; | |
371 | /// | |
372 | /// println!("The origin is: {:#?}", origin); | |
373 | /// ``` | |
374 | /// | |
375 | /// This outputs: | |
376 | /// | |
377 | /// ```text | |
378 | /// The origin is: Point { | |
379 | /// x: 0, | |
380 | /// y: 0 | |
381 | /// } | |
382 | /// ``` | |
85aaf69f SL |
383 | #[stable(feature = "rust1", since = "1.0.0")] |
384 | #[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \ | |
385 | defined in your crate, add `#[derive(Debug)]` or \ | |
386 | manually implement it"] | |
387 | #[lang = "debug_trait"] | |
388 | pub trait Debug { | |
389 | /// Formats the value using the given formatter. | |
390 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
391 | fn fmt(&self, &mut Formatter) -> Result; |
392 | } | |
393 | ||
c1a9b12d SL |
394 | /// Format trait for an empty format, `{}`. |
395 | /// | |
396 | /// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing | |
397 | /// output, and so cannot be derived. | |
398 | /// | |
399 | /// [debug]: trait.Debug.html | |
400 | /// | |
401 | /// For more information on formatters, see [the module-level documentation][module]. | |
402 | /// | |
b039eaaf | 403 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
404 | /// |
405 | /// # Examples | |
406 | /// | |
407 | /// Implementing `Display` on a type: | |
408 | /// | |
409 | /// ``` | |
410 | /// use std::fmt; | |
411 | /// | |
412 | /// struct Point { | |
413 | /// x: i32, | |
414 | /// y: i32, | |
415 | /// } | |
416 | /// | |
417 | /// impl fmt::Display for Point { | |
418 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
419 | /// write!(f, "({}, {})", self.x, self.y) | |
420 | /// } | |
421 | /// } | |
422 | /// | |
423 | /// let origin = Point { x: 0, y: 0 }; | |
424 | /// | |
425 | /// println!("The origin is: {}", origin); | |
426 | /// ``` | |
85aaf69f SL |
427 | #[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \ |
428 | formatter; try using `:?` instead if you are using \ | |
429 | a format string"] | |
430 | #[stable(feature = "rust1", since = "1.0.0")] | |
431 | pub trait Display { | |
432 | /// Formats the value using the given formatter. | |
433 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
434 | fn fmt(&self, &mut Formatter) -> Result; |
435 | } | |
436 | ||
c1a9b12d SL |
437 | /// Format trait for the `o` character. |
438 | /// | |
439 | /// The `Octal` trait should format its output as a number in base-8. | |
440 | /// | |
441 | /// The alternate flag, `#`, adds a `0o` in front of the output. | |
442 | /// | |
443 | /// For more information on formatters, see [the module-level documentation][module]. | |
444 | /// | |
b039eaaf | 445 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
446 | /// |
447 | /// # Examples | |
448 | /// | |
449 | /// Basic usage with `i32`: | |
450 | /// | |
451 | /// ``` | |
452 | /// let x = 42; // 42 is '52' in octal | |
453 | /// | |
454 | /// assert_eq!(format!("{:o}", x), "52"); | |
455 | /// assert_eq!(format!("{:#o}", x), "0o52"); | |
456 | /// ``` | |
457 | /// | |
458 | /// Implementing `Octal` on a type: | |
459 | /// | |
460 | /// ``` | |
461 | /// use std::fmt; | |
462 | /// | |
463 | /// struct Length(i32); | |
464 | /// | |
465 | /// impl fmt::Octal for Length { | |
466 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
467 | /// let val = self.0; | |
468 | /// | |
469 | /// write!(f, "{:o}", val) // delegate to i32's implementation | |
470 | /// } | |
471 | /// } | |
472 | /// | |
473 | /// let l = Length(9); | |
474 | /// | |
475 | /// println!("l as octal is: {:o}", l); | |
476 | /// ``` | |
85aaf69f | 477 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
478 | pub trait Octal { |
479 | /// Formats the value using the given formatter. | |
85aaf69f | 480 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
481 | fn fmt(&self, &mut Formatter) -> Result; |
482 | } | |
483 | ||
c1a9b12d SL |
484 | /// Format trait for the `b` character. |
485 | /// | |
486 | /// The `Binary` trait should format its output as a number in binary. | |
487 | /// | |
488 | /// The alternate flag, `#`, adds a `0b` in front of the output. | |
489 | /// | |
490 | /// For more information on formatters, see [the module-level documentation][module]. | |
491 | /// | |
b039eaaf | 492 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
493 | /// |
494 | /// # Examples | |
495 | /// | |
496 | /// Basic usage with `i32`: | |
497 | /// | |
498 | /// ``` | |
499 | /// let x = 42; // 42 is '101010' in binary | |
500 | /// | |
501 | /// assert_eq!(format!("{:b}", x), "101010"); | |
502 | /// assert_eq!(format!("{:#b}", x), "0b101010"); | |
503 | /// ``` | |
504 | /// | |
505 | /// Implementing `Binary` on a type: | |
506 | /// | |
507 | /// ``` | |
508 | /// use std::fmt; | |
509 | /// | |
510 | /// struct Length(i32); | |
511 | /// | |
512 | /// impl fmt::Binary for Length { | |
513 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
514 | /// let val = self.0; | |
515 | /// | |
516 | /// write!(f, "{:b}", val) // delegate to i32's implementation | |
517 | /// } | |
518 | /// } | |
519 | /// | |
520 | /// let l = Length(107); | |
521 | /// | |
522 | /// println!("l as binary is: {:b}", l); | |
523 | /// ``` | |
85aaf69f | 524 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
525 | pub trait Binary { |
526 | /// Formats the value using the given formatter. | |
85aaf69f | 527 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
528 | fn fmt(&self, &mut Formatter) -> Result; |
529 | } | |
530 | ||
c1a9b12d SL |
531 | /// Format trait for the `x` character. |
532 | /// | |
b039eaaf | 533 | /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` |
c1a9b12d SL |
534 | /// in lower case. |
535 | /// | |
536 | /// The alternate flag, `#`, adds a `0x` in front of the output. | |
537 | /// | |
538 | /// For more information on formatters, see [the module-level documentation][module]. | |
539 | /// | |
b039eaaf | 540 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
541 | /// |
542 | /// # Examples | |
543 | /// | |
544 | /// Basic usage with `i32`: | |
545 | /// | |
546 | /// ``` | |
547 | /// let x = 42; // 42 is '2a' in hex | |
548 | /// | |
549 | /// assert_eq!(format!("{:x}", x), "2a"); | |
550 | /// assert_eq!(format!("{:#x}", x), "0x2a"); | |
551 | /// ``` | |
552 | /// | |
553 | /// Implementing `LowerHex` on a type: | |
554 | /// | |
555 | /// ``` | |
556 | /// use std::fmt; | |
557 | /// | |
558 | /// struct Length(i32); | |
559 | /// | |
560 | /// impl fmt::LowerHex for Length { | |
561 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
562 | /// let val = self.0; | |
563 | /// | |
564 | /// write!(f, "{:x}", val) // delegate to i32's implementation | |
565 | /// } | |
566 | /// } | |
567 | /// | |
568 | /// let l = Length(9); | |
569 | /// | |
570 | /// println!("l as hex is: {:x}", l); | |
571 | /// ``` | |
85aaf69f | 572 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
573 | pub trait LowerHex { |
574 | /// Formats the value using the given formatter. | |
85aaf69f | 575 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
576 | fn fmt(&self, &mut Formatter) -> Result; |
577 | } | |
578 | ||
c1a9b12d SL |
579 | /// Format trait for the `X` character. |
580 | /// | |
b039eaaf | 581 | /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` |
c1a9b12d SL |
582 | /// in upper case. |
583 | /// | |
584 | /// The alternate flag, `#`, adds a `0x` in front of the output. | |
585 | /// | |
586 | /// For more information on formatters, see [the module-level documentation][module]. | |
587 | /// | |
b039eaaf | 588 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
589 | /// |
590 | /// # Examples | |
591 | /// | |
592 | /// Basic usage with `i32`: | |
593 | /// | |
594 | /// ``` | |
595 | /// let x = 42; // 42 is '2A' in hex | |
596 | /// | |
597 | /// assert_eq!(format!("{:X}", x), "2A"); | |
598 | /// assert_eq!(format!("{:#X}", x), "0x2A"); | |
599 | /// ``` | |
600 | /// | |
601 | /// Implementing `UpperHex` on a type: | |
602 | /// | |
603 | /// ``` | |
604 | /// use std::fmt; | |
605 | /// | |
606 | /// struct Length(i32); | |
607 | /// | |
608 | /// impl fmt::UpperHex for Length { | |
609 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
610 | /// let val = self.0; | |
611 | /// | |
612 | /// write!(f, "{:X}", val) // delegate to i32's implementation | |
613 | /// } | |
614 | /// } | |
615 | /// | |
616 | /// let l = Length(9); | |
617 | /// | |
618 | /// println!("l as hex is: {:X}", l); | |
619 | /// ``` | |
85aaf69f | 620 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
621 | pub trait UpperHex { |
622 | /// Formats the value using the given formatter. | |
85aaf69f | 623 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
624 | fn fmt(&self, &mut Formatter) -> Result; |
625 | } | |
626 | ||
c1a9b12d SL |
627 | /// Format trait for the `p` character. |
628 | /// | |
629 | /// The `Pointer` trait should format its output as a memory location. This is commonly presented | |
b039eaaf | 630 | /// as hexadecimal. |
c1a9b12d SL |
631 | /// |
632 | /// For more information on formatters, see [the module-level documentation][module]. | |
633 | /// | |
b039eaaf | 634 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
635 | /// |
636 | /// # Examples | |
637 | /// | |
638 | /// Basic usage with `&i32`: | |
639 | /// | |
640 | /// ``` | |
641 | /// let x = &42; | |
642 | /// | |
643 | /// let address = format!("{:p}", x); // this produces something like '0x7f06092ac6d0' | |
644 | /// ``` | |
645 | /// | |
646 | /// Implementing `Pointer` on a type: | |
647 | /// | |
648 | /// ``` | |
649 | /// use std::fmt; | |
650 | /// | |
651 | /// struct Length(i32); | |
652 | /// | |
653 | /// impl fmt::Pointer for Length { | |
654 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
655 | /// // use `as` to convert to a `*const T`, which implements Pointer, which we can use | |
656 | /// | |
657 | /// write!(f, "{:p}", self as *const Length) | |
658 | /// } | |
659 | /// } | |
660 | /// | |
661 | /// let l = Length(42); | |
662 | /// | |
663 | /// println!("l is in memory here: {:p}", l); | |
664 | /// ``` | |
85aaf69f | 665 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
666 | pub trait Pointer { |
667 | /// Formats the value using the given formatter. | |
85aaf69f | 668 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
669 | fn fmt(&self, &mut Formatter) -> Result; |
670 | } | |
671 | ||
c1a9b12d SL |
672 | /// Format trait for the `e` character. |
673 | /// | |
674 | /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. | |
675 | /// | |
676 | /// For more information on formatters, see [the module-level documentation][module]. | |
677 | /// | |
b039eaaf | 678 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
679 | /// |
680 | /// # Examples | |
681 | /// | |
682 | /// Basic usage with `i32`: | |
683 | /// | |
684 | /// ``` | |
685 | /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation | |
686 | /// | |
687 | /// assert_eq!(format!("{:e}", x), "4.2e1"); | |
688 | /// ``` | |
689 | /// | |
690 | /// Implementing `LowerExp` on a type: | |
691 | /// | |
692 | /// ``` | |
693 | /// use std::fmt; | |
694 | /// | |
695 | /// struct Length(i32); | |
696 | /// | |
697 | /// impl fmt::LowerExp for Length { | |
698 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
699 | /// let val = self.0; | |
700 | /// write!(f, "{}e1", val / 10) | |
701 | /// } | |
702 | /// } | |
703 | /// | |
704 | /// let l = Length(100); | |
705 | /// | |
706 | /// println!("l in scientific notation is: {:e}", l); | |
707 | /// ``` | |
85aaf69f | 708 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
709 | pub trait LowerExp { |
710 | /// Formats the value using the given formatter. | |
85aaf69f | 711 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
712 | fn fmt(&self, &mut Formatter) -> Result; |
713 | } | |
714 | ||
c1a9b12d SL |
715 | /// Format trait for the `E` character. |
716 | /// | |
717 | /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. | |
718 | /// | |
719 | /// For more information on formatters, see [the module-level documentation][module]. | |
720 | /// | |
b039eaaf | 721 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
722 | /// |
723 | /// # Examples | |
724 | /// | |
725 | /// Basic usage with `f32`: | |
726 | /// | |
727 | /// ``` | |
728 | /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation | |
729 | /// | |
730 | /// assert_eq!(format!("{:E}", x), "4.2E1"); | |
731 | /// ``` | |
732 | /// | |
733 | /// Implementing `UpperExp` on a type: | |
734 | /// | |
735 | /// ``` | |
736 | /// use std::fmt; | |
737 | /// | |
738 | /// struct Length(i32); | |
739 | /// | |
740 | /// impl fmt::UpperExp for Length { | |
741 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
742 | /// let val = self.0; | |
743 | /// write!(f, "{}E1", val / 10) | |
744 | /// } | |
745 | /// } | |
746 | /// | |
747 | /// let l = Length(100); | |
748 | /// | |
749 | /// println!("l in scientific notation is: {:E}", l); | |
750 | /// ``` | |
85aaf69f | 751 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
752 | pub trait UpperExp { |
753 | /// Formats the value using the given formatter. | |
85aaf69f | 754 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
755 | fn fmt(&self, &mut Formatter) -> Result; |
756 | } | |
757 | ||
758 | /// The `write` function takes an output stream, a precompiled format string, | |
759 | /// and a list of arguments. The arguments will be formatted according to the | |
760 | /// specified format string into the output stream provided. | |
761 | /// | |
762 | /// # Arguments | |
763 | /// | |
764 | /// * output - the buffer to write output to | |
765 | /// * args - the precompiled arguments generated by `format_args!` | |
85aaf69f SL |
766 | #[stable(feature = "rust1", since = "1.0.0")] |
767 | pub fn write(output: &mut Write, args: Arguments) -> Result { | |
1a4d82fc JJ |
768 | let mut formatter = Formatter { |
769 | flags: 0, | |
770 | width: None, | |
771 | precision: None, | |
772 | buf: output, | |
85aaf69f | 773 | align: Alignment::Unknown, |
1a4d82fc JJ |
774 | fill: ' ', |
775 | args: args.args, | |
776 | curarg: args.args.iter(), | |
777 | }; | |
778 | ||
779 | let mut pieces = args.pieces.iter(); | |
780 | ||
781 | match args.fmt { | |
782 | None => { | |
783 | // We can use default formatting parameters for all arguments. | |
784 | for (arg, piece) in args.args.iter().zip(pieces.by_ref()) { | |
785 | try!(formatter.buf.write_str(*piece)); | |
786 | try!((arg.formatter)(arg.value, &mut formatter)); | |
787 | } | |
788 | } | |
789 | Some(fmt) => { | |
790 | // Every spec has a corresponding argument that is preceded by | |
791 | // a string piece. | |
792 | for (arg, piece) in fmt.iter().zip(pieces.by_ref()) { | |
793 | try!(formatter.buf.write_str(*piece)); | |
794 | try!(formatter.run(arg)); | |
795 | } | |
796 | } | |
797 | } | |
798 | ||
799 | // There can be only one trailing string piece left. | |
800 | match pieces.next() { | |
801 | Some(piece) => { | |
802 | try!(formatter.buf.write_str(*piece)); | |
803 | } | |
804 | None => {} | |
805 | } | |
806 | ||
807 | Ok(()) | |
808 | } | |
809 | ||
810 | impl<'a> Formatter<'a> { | |
811 | ||
812 | // First up is the collection of functions used to execute a format string | |
813 | // at runtime. This consumes all of the compile-time statics generated by | |
814 | // the format! syntax extension. | |
85aaf69f | 815 | fn run(&mut self, arg: &rt::v1::Argument) -> Result { |
1a4d82fc JJ |
816 | // Fill in the format parameters into the formatter |
817 | self.fill = arg.format.fill; | |
818 | self.align = arg.format.align; | |
819 | self.flags = arg.format.flags; | |
820 | self.width = self.getcount(&arg.format.width); | |
821 | self.precision = self.getcount(&arg.format.precision); | |
822 | ||
823 | // Extract the correct argument | |
824 | let value = match arg.position { | |
85aaf69f SL |
825 | rt::v1::Position::Next => { *self.curarg.next().unwrap() } |
826 | rt::v1::Position::At(i) => self.args[i], | |
1a4d82fc JJ |
827 | }; |
828 | ||
829 | // Then actually do some printing | |
830 | (value.formatter)(value.value, self) | |
831 | } | |
832 | ||
c34b1796 | 833 | fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> { |
1a4d82fc | 834 | match *cnt { |
85aaf69f SL |
835 | rt::v1::Count::Is(n) => Some(n), |
836 | rt::v1::Count::Implied => None, | |
837 | rt::v1::Count::Param(i) => { | |
c34b1796 | 838 | self.args[i].as_usize() |
1a4d82fc | 839 | } |
85aaf69f | 840 | rt::v1::Count::NextParam => { |
c34b1796 | 841 | self.curarg.next().and_then(|arg| arg.as_usize()) |
1a4d82fc JJ |
842 | } |
843 | } | |
844 | } | |
845 | ||
846 | // Helper methods used for padding and processing formatting arguments that | |
847 | // all formatting traits can use. | |
848 | ||
849 | /// Performs the correct padding for an integer which has already been | |
85aaf69f SL |
850 | /// emitted into a str. The str should *not* contain the sign for the |
851 | /// integer, that will be added by this method. | |
1a4d82fc JJ |
852 | /// |
853 | /// # Arguments | |
854 | /// | |
855 | /// * is_positive - whether the original integer was positive or not. | |
c34b1796 | 856 | /// * prefix - if the '#' character (Alternate) is provided, this |
1a4d82fc JJ |
857 | /// is the prefix to put in front of the number. |
858 | /// * buf - the byte array that the number has been formatted into | |
859 | /// | |
860 | /// This function will correctly account for the flags provided as well as | |
861 | /// the minimum width. It will not take precision into account. | |
85aaf69f | 862 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
863 | pub fn pad_integral(&mut self, |
864 | is_positive: bool, | |
865 | prefix: &str, | |
866 | buf: &str) | |
867 | -> Result { | |
868 | use char::CharExt; | |
1a4d82fc JJ |
869 | |
870 | let mut width = buf.len(); | |
871 | ||
872 | let mut sign = None; | |
873 | if !is_positive { | |
874 | sign = Some('-'); width += 1; | |
b039eaaf | 875 | } else if self.sign_plus() { |
1a4d82fc JJ |
876 | sign = Some('+'); width += 1; |
877 | } | |
878 | ||
879 | let mut prefixed = false; | |
b039eaaf | 880 | if self.alternate() { |
92a42be0 | 881 | prefixed = true; width += prefix.chars().count(); |
1a4d82fc JJ |
882 | } |
883 | ||
884 | // Writes the sign if it exists, and then the prefix if it was requested | |
85aaf69f SL |
885 | let write_prefix = |f: &mut Formatter| { |
886 | if let Some(c) = sign { | |
1a4d82fc JJ |
887 | let mut b = [0; 4]; |
888 | let n = c.encode_utf8(&mut b).unwrap_or(0); | |
85aaf69f | 889 | let b = unsafe { str::from_utf8_unchecked(&b[..n]) }; |
1a4d82fc JJ |
890 | try!(f.buf.write_str(b)); |
891 | } | |
892 | if prefixed { f.buf.write_str(prefix) } | |
893 | else { Ok(()) } | |
894 | }; | |
895 | ||
896 | // The `width` field is more of a `min-width` parameter at this point. | |
897 | match self.width { | |
898 | // If there's no minimum length requirements then we can just | |
899 | // write the bytes. | |
900 | None => { | |
901 | try!(write_prefix(self)); self.buf.write_str(buf) | |
902 | } | |
903 | // Check if we're over the minimum width, if so then we can also | |
904 | // just write the bytes. | |
905 | Some(min) if width >= min => { | |
906 | try!(write_prefix(self)); self.buf.write_str(buf) | |
907 | } | |
908 | // The sign and prefix goes before the padding if the fill character | |
909 | // is zero | |
b039eaaf | 910 | Some(min) if self.sign_aware_zero_pad() => { |
1a4d82fc JJ |
911 | self.fill = '0'; |
912 | try!(write_prefix(self)); | |
85aaf69f | 913 | self.with_padding(min - width, Alignment::Right, |f| { |
1a4d82fc JJ |
914 | f.buf.write_str(buf) |
915 | }) | |
916 | } | |
917 | // Otherwise, the sign and prefix goes after the padding | |
918 | Some(min) => { | |
85aaf69f | 919 | self.with_padding(min - width, Alignment::Right, |f| { |
1a4d82fc JJ |
920 | try!(write_prefix(f)); f.buf.write_str(buf) |
921 | }) | |
922 | } | |
923 | } | |
924 | } | |
925 | ||
926 | /// This function takes a string slice and emits it to the internal buffer | |
927 | /// after applying the relevant formatting flags specified. The flags | |
928 | /// recognized for generic strings are: | |
929 | /// | |
930 | /// * width - the minimum width of what to emit | |
931 | /// * fill/align - what to emit and where to emit it if the string | |
932 | /// provided needs to be padded | |
933 | /// * precision - the maximum length to emit, the string is truncated if it | |
934 | /// is longer than this length | |
935 | /// | |
936 | /// Notably this function ignored the `flag` parameters | |
85aaf69f | 937 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
938 | pub fn pad(&mut self, s: &str) -> Result { |
939 | // Make sure there's a fast path up front | |
940 | if self.width.is_none() && self.precision.is_none() { | |
941 | return self.buf.write_str(s); | |
942 | } | |
943 | // The `precision` field can be interpreted as a `max-width` for the | |
944 | // string being formatted | |
92a42be0 SL |
945 | if let Some(max) = self.precision { |
946 | // If there's a maximum width and our string is longer than | |
947 | // that, then we must always have truncation. This is the only | |
948 | // case where the maximum length will matter. | |
949 | if let Some((i, _)) = s.char_indices().skip(max).next() { | |
950 | return self.buf.write_str(&s[..i]) | |
1a4d82fc | 951 | } |
1a4d82fc JJ |
952 | } |
953 | // The `width` field is more of a `min-width` parameter at this point. | |
954 | match self.width { | |
955 | // If we're under the maximum length, and there's no minimum length | |
956 | // requirements, then we can just emit the string | |
957 | None => self.buf.write_str(s), | |
958 | // If we're under the maximum width, check if we're over the minimum | |
959 | // width, if so it's as easy as just emitting the string. | |
92a42be0 | 960 | Some(width) if s.chars().count() >= width => { |
1a4d82fc JJ |
961 | self.buf.write_str(s) |
962 | } | |
963 | // If we're under both the maximum and the minimum width, then fill | |
964 | // up the minimum width with the specified string + some alignment. | |
965 | Some(width) => { | |
92a42be0 | 966 | self.with_padding(width - s.chars().count(), Alignment::Left, |me| { |
1a4d82fc JJ |
967 | me.buf.write_str(s) |
968 | }) | |
969 | } | |
970 | } | |
971 | } | |
972 | ||
973 | /// Runs a callback, emitting the correct padding either before or | |
974 | /// afterwards depending on whether right or left alignment is requested. | |
c34b1796 | 975 | fn with_padding<F>(&mut self, padding: usize, default: Alignment, |
85aaf69f SL |
976 | f: F) -> Result |
977 | where F: FnOnce(&mut Formatter) -> Result, | |
1a4d82fc JJ |
978 | { |
979 | use char::CharExt; | |
980 | let align = match self.align { | |
85aaf69f | 981 | Alignment::Unknown => default, |
1a4d82fc JJ |
982 | _ => self.align |
983 | }; | |
984 | ||
985 | let (pre_pad, post_pad) = match align { | |
85aaf69f SL |
986 | Alignment::Left => (0, padding), |
987 | Alignment::Right | Alignment::Unknown => (padding, 0), | |
988 | Alignment::Center => (padding / 2, (padding + 1) / 2), | |
1a4d82fc JJ |
989 | }; |
990 | ||
c34b1796 | 991 | let mut fill = [0; 4]; |
1a4d82fc JJ |
992 | let len = self.fill.encode_utf8(&mut fill).unwrap_or(0); |
993 | let fill = unsafe { str::from_utf8_unchecked(&fill[..len]) }; | |
994 | ||
85aaf69f | 995 | for _ in 0..pre_pad { |
1a4d82fc JJ |
996 | try!(self.buf.write_str(fill)); |
997 | } | |
998 | ||
999 | try!(f(self)); | |
1000 | ||
85aaf69f | 1001 | for _ in 0..post_pad { |
1a4d82fc JJ |
1002 | try!(self.buf.write_str(fill)); |
1003 | } | |
1004 | ||
1005 | Ok(()) | |
1006 | } | |
1007 | ||
d9579d0f AL |
1008 | /// Takes the formatted parts and applies the padding. |
1009 | /// Assumes that the caller already has rendered the parts with required precision, | |
1010 | /// so that `self.precision` can be ignored. | |
1011 | fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
1012 | if let Some(mut width) = self.width { | |
1013 | // for the sign-aware zero padding, we render the sign first and | |
1014 | // behave as if we had no sign from the beginning. | |
1015 | let mut formatted = formatted.clone(); | |
1016 | let mut align = self.align; | |
1017 | let old_fill = self.fill; | |
b039eaaf | 1018 | if self.sign_aware_zero_pad() { |
d9579d0f AL |
1019 | // a sign always goes first |
1020 | let sign = unsafe { str::from_utf8_unchecked(formatted.sign) }; | |
1021 | try!(self.buf.write_str(sign)); | |
1022 | ||
1023 | // remove the sign from the formatted parts | |
1024 | formatted.sign = b""; | |
1025 | width = if width < sign.len() { 0 } else { width - sign.len() }; | |
1026 | align = Alignment::Right; | |
1027 | self.fill = '0'; | |
1028 | } | |
1029 | ||
1030 | // remaining parts go through the ordinary padding process. | |
1031 | let len = formatted.len(); | |
1032 | let ret = if width <= len { // no padding | |
1033 | self.write_formatted_parts(&formatted) | |
1034 | } else { | |
1035 | self.with_padding(width - len, align, |f| { | |
1036 | f.write_formatted_parts(&formatted) | |
1037 | }) | |
1038 | }; | |
1039 | self.fill = old_fill; | |
1040 | ret | |
1041 | } else { | |
1042 | // this is the common case and we take a shortcut | |
1043 | self.write_formatted_parts(formatted) | |
1044 | } | |
1045 | } | |
1046 | ||
1047 | fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
1048 | fn write_bytes(buf: &mut Write, s: &[u8]) -> Result { | |
1049 | buf.write_str(unsafe { str::from_utf8_unchecked(s) }) | |
1050 | } | |
1051 | ||
1052 | if !formatted.sign.is_empty() { | |
1053 | try!(write_bytes(self.buf, formatted.sign)); | |
1054 | } | |
1055 | for part in formatted.parts { | |
1056 | match *part { | |
1057 | flt2dec::Part::Zero(mut nzeroes) => { | |
1058 | const ZEROES: &'static str = // 64 zeroes | |
1059 | "0000000000000000000000000000000000000000000000000000000000000000"; | |
1060 | while nzeroes > ZEROES.len() { | |
1061 | try!(self.buf.write_str(ZEROES)); | |
1062 | nzeroes -= ZEROES.len(); | |
1063 | } | |
1064 | if nzeroes > 0 { | |
1065 | try!(self.buf.write_str(&ZEROES[..nzeroes])); | |
1066 | } | |
1067 | } | |
1068 | flt2dec::Part::Num(mut v) => { | |
1069 | let mut s = [0; 5]; | |
1070 | let len = part.len(); | |
1071 | for c in s[..len].iter_mut().rev() { | |
1072 | *c = b'0' + (v % 10) as u8; | |
1073 | v /= 10; | |
1074 | } | |
1075 | try!(write_bytes(self.buf, &s[..len])); | |
1076 | } | |
1077 | flt2dec::Part::Copy(buf) => { | |
1078 | try!(write_bytes(self.buf, buf)); | |
1079 | } | |
1080 | } | |
1081 | } | |
1082 | Ok(()) | |
1083 | } | |
1084 | ||
1a4d82fc JJ |
1085 | /// Writes some data to the underlying buffer contained within this |
1086 | /// formatter. | |
85aaf69f | 1087 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1088 | pub fn write_str(&mut self, data: &str) -> Result { |
1089 | self.buf.write_str(data) | |
1090 | } | |
1091 | ||
1092 | /// Writes some formatted information into this instance | |
85aaf69f | 1093 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1094 | pub fn write_fmt(&mut self, fmt: Arguments) -> Result { |
1095 | write(self.buf, fmt) | |
1096 | } | |
1097 | ||
1098 | /// Flags for formatting (packed version of rt::Flag) | |
85aaf69f | 1099 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 1100 | pub fn flags(&self) -> u32 { self.flags } |
1a4d82fc JJ |
1101 | |
1102 | /// Character used as 'fill' whenever there is alignment | |
b039eaaf | 1103 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1a4d82fc JJ |
1104 | pub fn fill(&self) -> char { self.fill } |
1105 | ||
1106 | /// Flag indicating what form of alignment was requested | |
b039eaaf | 1107 | #[unstable(feature = "fmt_flags_align", reason = "method was just created", |
e9174d1e | 1108 | issue = "27726")] |
85aaf69f | 1109 | pub fn align(&self) -> Alignment { self.align } |
1a4d82fc JJ |
1110 | |
1111 | /// Optionally specified integer width that the output should be | |
b039eaaf | 1112 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
c34b1796 | 1113 | pub fn width(&self) -> Option<usize> { self.width } |
1a4d82fc JJ |
1114 | |
1115 | /// Optionally specified precision for numeric types | |
b039eaaf | 1116 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
c34b1796 AL |
1117 | pub fn precision(&self) -> Option<usize> { self.precision } |
1118 | ||
b039eaaf SL |
1119 | /// Determines if the `+` flag was specified. |
1120 | #[stable(feature = "fmt_flags", since = "1.5.0")] | |
1121 | pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 } | |
1122 | ||
1123 | /// Determines if the `-` flag was specified. | |
1124 | #[stable(feature = "fmt_flags", since = "1.5.0")] | |
1125 | pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 } | |
1126 | ||
1127 | /// Determines if the `#` flag was specified. | |
1128 | #[stable(feature = "fmt_flags", since = "1.5.0")] | |
1129 | pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 } | |
1130 | ||
1131 | /// Determines if the `0` flag was specified. | |
1132 | #[stable(feature = "fmt_flags", since = "1.5.0")] | |
1133 | pub fn sign_aware_zero_pad(&self) -> bool { | |
1134 | self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 | |
1135 | } | |
1136 | ||
c34b1796 AL |
1137 | /// Creates a `DebugStruct` builder designed to assist with creation of |
1138 | /// `fmt::Debug` implementations for structs. | |
1139 | /// | |
1140 | /// # Examples | |
1141 | /// | |
1142 | /// ```rust | |
c34b1796 AL |
1143 | /// use std::fmt; |
1144 | /// | |
1145 | /// struct Foo { | |
1146 | /// bar: i32, | |
1147 | /// baz: String, | |
1148 | /// } | |
1149 | /// | |
1150 | /// impl fmt::Debug for Foo { | |
1151 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1152 | /// fmt.debug_struct("Foo") | |
1153 | /// .field("bar", &self.bar) | |
1154 | /// .field("baz", &self.baz) | |
1155 | /// .finish() | |
1156 | /// } | |
1157 | /// } | |
1158 | /// | |
1159 | /// // prints "Foo { bar: 10, baz: "Hello World" }" | |
1160 | /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); | |
1161 | /// ``` | |
62682a34 | 1162 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1163 | #[inline] |
1164 | pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { | |
1165 | builders::debug_struct_new(self, name) | |
1166 | } | |
1167 | ||
1168 | /// Creates a `DebugTuple` builder designed to assist with creation of | |
1169 | /// `fmt::Debug` implementations for tuple structs. | |
1170 | /// | |
1171 | /// # Examples | |
1172 | /// | |
1173 | /// ```rust | |
c34b1796 AL |
1174 | /// use std::fmt; |
1175 | /// | |
1176 | /// struct Foo(i32, String); | |
1177 | /// | |
1178 | /// impl fmt::Debug for Foo { | |
1179 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1180 | /// fmt.debug_tuple("Foo") | |
1181 | /// .field(&self.0) | |
1182 | /// .field(&self.1) | |
1183 | /// .finish() | |
1184 | /// } | |
1185 | /// } | |
1186 | /// | |
1187 | /// // prints "Foo(10, "Hello World")" | |
1188 | /// println!("{:?}", Foo(10, "Hello World".to_string())); | |
1189 | /// ``` | |
62682a34 | 1190 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1191 | #[inline] |
1192 | pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { | |
1193 | builders::debug_tuple_new(self, name) | |
1194 | } | |
1195 | ||
1196 | /// Creates a `DebugList` builder designed to assist with creation of | |
1197 | /// `fmt::Debug` implementations for list-like structures. | |
1198 | /// | |
1199 | /// # Examples | |
1200 | /// | |
1201 | /// ```rust | |
c34b1796 AL |
1202 | /// use std::fmt; |
1203 | /// | |
1204 | /// struct Foo(Vec<i32>); | |
1205 | /// | |
1206 | /// impl fmt::Debug for Foo { | |
1207 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1208 | /// fmt.debug_list().entries(self.0.iter()).finish() |
c34b1796 AL |
1209 | /// } |
1210 | /// } | |
1211 | /// | |
1212 | /// // prints "[10, 11]" | |
1213 | /// println!("{:?}", Foo(vec![10, 11])); | |
1214 | /// ``` | |
62682a34 | 1215 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1216 | #[inline] |
1217 | pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { | |
1218 | builders::debug_list_new(self) | |
1219 | } | |
1220 | ||
1221 | /// Creates a `DebugSet` builder designed to assist with creation of | |
1222 | /// `fmt::Debug` implementations for set-like structures. | |
1223 | /// | |
1224 | /// # Examples | |
1225 | /// | |
1226 | /// ```rust | |
c34b1796 AL |
1227 | /// use std::fmt; |
1228 | /// | |
1229 | /// struct Foo(Vec<i32>); | |
1230 | /// | |
1231 | /// impl fmt::Debug for Foo { | |
1232 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1233 | /// fmt.debug_set().entries(self.0.iter()).finish() |
c34b1796 AL |
1234 | /// } |
1235 | /// } | |
1236 | /// | |
1237 | /// // prints "{10, 11}" | |
1238 | /// println!("{:?}", Foo(vec![10, 11])); | |
1239 | /// ``` | |
62682a34 | 1240 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1241 | #[inline] |
1242 | pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { | |
1243 | builders::debug_set_new(self) | |
1244 | } | |
1245 | ||
1246 | /// Creates a `DebugMap` builder designed to assist with creation of | |
1247 | /// `fmt::Debug` implementations for map-like structures. | |
1248 | /// | |
1249 | /// # Examples | |
1250 | /// | |
1251 | /// ```rust | |
c34b1796 AL |
1252 | /// use std::fmt; |
1253 | /// | |
1254 | /// struct Foo(Vec<(String, i32)>); | |
1255 | /// | |
1256 | /// impl fmt::Debug for Foo { | |
1257 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1258 | /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() |
c34b1796 AL |
1259 | /// } |
1260 | /// } | |
1261 | /// | |
1262 | /// // prints "{"A": 10, "B": 11}" | |
1263 | /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); | |
1264 | /// ``` | |
62682a34 | 1265 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1266 | #[inline] |
1267 | pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { | |
1268 | builders::debug_map_new(self) | |
1269 | } | |
1a4d82fc JJ |
1270 | } |
1271 | ||
62682a34 SL |
1272 | #[stable(since = "1.2.0", feature = "formatter_write")] |
1273 | impl<'a> Write for Formatter<'a> { | |
1274 | fn write_str(&mut self, s: &str) -> Result { | |
1275 | self.buf.write_str(s) | |
1276 | } | |
1277 | ||
1278 | fn write_char(&mut self, c: char) -> Result { | |
1279 | self.buf.write_char(c) | |
1280 | } | |
1281 | ||
1282 | fn write_fmt(&mut self, args: Arguments) -> Result { | |
1283 | write(self.buf, args) | |
1284 | } | |
1285 | } | |
1286 | ||
85aaf69f SL |
1287 | #[stable(feature = "rust1", since = "1.0.0")] |
1288 | impl Display for Error { | |
1a4d82fc | 1289 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1290 | Display::fmt("an error occurred when formatting an argument", f) |
1a4d82fc JJ |
1291 | } |
1292 | } | |
1293 | ||
1a4d82fc JJ |
1294 | // Implementations of the core formatting traits |
1295 | ||
1296 | macro_rules! fmt_refs { | |
1297 | ($($tr:ident),*) => { | |
1298 | $( | |
85aaf69f | 1299 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1300 | impl<'a, T: ?Sized + $tr> $tr for &'a T { |
1301 | fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
1302 | } | |
85aaf69f | 1303 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1304 | impl<'a, T: ?Sized + $tr> $tr for &'a mut T { |
1305 | fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
1306 | } | |
1307 | )* | |
1308 | } | |
1309 | } | |
1310 | ||
85aaf69f | 1311 | fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } |
1a4d82fc | 1312 | |
85aaf69f SL |
1313 | #[stable(feature = "rust1", since = "1.0.0")] |
1314 | impl Debug for bool { | |
1a4d82fc | 1315 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1316 | Display::fmt(self, f) |
1a4d82fc JJ |
1317 | } |
1318 | } | |
1319 | ||
85aaf69f SL |
1320 | #[stable(feature = "rust1", since = "1.0.0")] |
1321 | impl Display for bool { | |
1a4d82fc | 1322 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1323 | Display::fmt(if *self { "true" } else { "false" }, f) |
1a4d82fc JJ |
1324 | } |
1325 | } | |
1326 | ||
85aaf69f SL |
1327 | #[stable(feature = "rust1", since = "1.0.0")] |
1328 | impl Debug for str { | |
1a4d82fc | 1329 | fn fmt(&self, f: &mut Formatter) -> Result { |
b039eaaf SL |
1330 | try!(f.write_char('"')); |
1331 | let mut from = 0; | |
1332 | for (i, c) in self.char_indices() { | |
1333 | let esc = c.escape_default(); | |
1334 | // If char needs escaping, flush backlog so far and write, else skip | |
1335 | if esc.size_hint() != (1, Some(1)) { | |
1336 | try!(f.write_str(&self[from..i])); | |
1337 | for c in esc { | |
1338 | try!(f.write_char(c)); | |
1339 | } | |
1340 | from = i + c.len_utf8(); | |
1341 | } | |
1a4d82fc | 1342 | } |
b039eaaf SL |
1343 | try!(f.write_str(&self[from..])); |
1344 | f.write_char('"') | |
1a4d82fc JJ |
1345 | } |
1346 | } | |
1347 | ||
85aaf69f SL |
1348 | #[stable(feature = "rust1", since = "1.0.0")] |
1349 | impl Display for str { | |
1a4d82fc JJ |
1350 | fn fmt(&self, f: &mut Formatter) -> Result { |
1351 | f.pad(self) | |
1352 | } | |
1353 | } | |
1354 | ||
85aaf69f SL |
1355 | #[stable(feature = "rust1", since = "1.0.0")] |
1356 | impl Debug for char { | |
1a4d82fc | 1357 | fn fmt(&self, f: &mut Formatter) -> Result { |
b039eaaf | 1358 | try!(f.write_char('\'')); |
1a4d82fc | 1359 | for c in self.escape_default() { |
c1a9b12d | 1360 | try!(f.write_char(c)) |
1a4d82fc | 1361 | } |
b039eaaf | 1362 | f.write_char('\'') |
1a4d82fc JJ |
1363 | } |
1364 | } | |
1365 | ||
85aaf69f SL |
1366 | #[stable(feature = "rust1", since = "1.0.0")] |
1367 | impl Display for char { | |
1a4d82fc | 1368 | fn fmt(&self, f: &mut Formatter) -> Result { |
62682a34 SL |
1369 | if f.width.is_none() && f.precision.is_none() { |
1370 | f.write_char(*self) | |
1371 | } else { | |
1372 | let mut utf8 = [0; 4]; | |
1373 | let amt = self.encode_utf8(&mut utf8).unwrap_or(0); | |
e9174d1e | 1374 | let s: &str = unsafe { str::from_utf8_unchecked(&utf8[..amt]) }; |
62682a34 SL |
1375 | f.pad(s) |
1376 | } | |
1a4d82fc JJ |
1377 | } |
1378 | } | |
1379 | ||
85aaf69f | 1380 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1381 | impl<T> Pointer for *const T { |
1382 | fn fmt(&self, f: &mut Formatter) -> Result { | |
9346a6ac AL |
1383 | let old_width = f.width; |
1384 | let old_flags = f.flags; | |
1385 | ||
1386 | // The alternate flag is already treated by LowerHex as being special- | |
1387 | // it denotes whether to prefix with 0x. We use it to work out whether | |
1388 | // or not to zero extend, and then unconditionally set it to get the | |
1389 | // prefix. | |
b039eaaf | 1390 | if f.alternate() { |
9346a6ac AL |
1391 | f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); |
1392 | ||
1393 | if let None = f.width { | |
e9174d1e | 1394 | f.width = Some((::usize::BITS/4) + 2); |
9346a6ac AL |
1395 | } |
1396 | } | |
c34b1796 | 1397 | f.flags |= 1 << (FlagV1::Alternate as u32); |
9346a6ac | 1398 | |
c34b1796 | 1399 | let ret = LowerHex::fmt(&(*self as usize), f); |
9346a6ac AL |
1400 | |
1401 | f.width = old_width; | |
1402 | f.flags = old_flags; | |
1403 | ||
1a4d82fc JJ |
1404 | ret |
1405 | } | |
1406 | } | |
1407 | ||
85aaf69f | 1408 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1409 | impl<T> Pointer for *mut T { |
1410 | fn fmt(&self, f: &mut Formatter) -> Result { | |
c34b1796 AL |
1411 | // FIXME(#23542) Replace with type ascription. |
1412 | #![allow(trivial_casts)] | |
1a4d82fc JJ |
1413 | Pointer::fmt(&(*self as *const T), f) |
1414 | } | |
1415 | } | |
1416 | ||
85aaf69f | 1417 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1418 | impl<'a, T> Pointer for &'a T { |
1419 | fn fmt(&self, f: &mut Formatter) -> Result { | |
c34b1796 AL |
1420 | // FIXME(#23542) Replace with type ascription. |
1421 | #![allow(trivial_casts)] | |
1a4d82fc JJ |
1422 | Pointer::fmt(&(*self as *const T), f) |
1423 | } | |
1424 | } | |
1425 | ||
85aaf69f | 1426 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1427 | impl<'a, T> Pointer for &'a mut T { |
1428 | fn fmt(&self, f: &mut Formatter) -> Result { | |
c34b1796 AL |
1429 | // FIXME(#23542) Replace with type ascription. |
1430 | #![allow(trivial_casts)] | |
1a4d82fc JJ |
1431 | Pointer::fmt(&(&**self as *const T), f) |
1432 | } | |
1433 | } | |
1434 | ||
9346a6ac | 1435 | // Common code of floating point Debug and Display. |
d9579d0f AL |
1436 | fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result |
1437 | where T: flt2dec::DecodableFloat | |
1438 | { | |
b039eaaf | 1439 | let force_sign = fmt.sign_plus(); |
d9579d0f AL |
1440 | let sign = match (force_sign, negative_zero) { |
1441 | (false, false) => flt2dec::Sign::Minus, | |
1442 | (false, true) => flt2dec::Sign::MinusRaw, | |
1443 | (true, false) => flt2dec::Sign::MinusPlus, | |
1444 | (true, true) => flt2dec::Sign::MinusPlusRaw, | |
1445 | }; | |
1446 | ||
1447 | let mut buf = [0; 1024]; // enough for f32 and f64 | |
1448 | let mut parts = [flt2dec::Part::Zero(0); 16]; | |
1449 | let formatted = if let Some(precision) = fmt.precision { | |
1450 | flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, *num, sign, | |
1451 | precision, false, &mut buf, &mut parts) | |
1452 | } else { | |
1453 | flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, sign, | |
1454 | 0, false, &mut buf, &mut parts) | |
1455 | }; | |
1456 | fmt.pad_formatted_parts(&formatted) | |
1457 | } | |
1458 | ||
1459 | // Common code of floating point LowerExp and UpperExp. | |
1460 | fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result | |
1461 | where T: flt2dec::DecodableFloat | |
1462 | { | |
b039eaaf | 1463 | let force_sign = fmt.sign_plus(); |
d9579d0f AL |
1464 | let sign = match force_sign { |
1465 | false => flt2dec::Sign::Minus, | |
1466 | true => flt2dec::Sign::MinusPlus, | |
1467 | }; | |
1468 | ||
1469 | let mut buf = [0; 1024]; // enough for f32 and f64 | |
1470 | let mut parts = [flt2dec::Part::Zero(0); 16]; | |
1471 | let formatted = if let Some(precision) = fmt.precision { | |
1472 | // 1 integral digit + `precision` fractional digits = `precision + 1` total digits | |
1473 | flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, *num, sign, | |
1474 | precision + 1, upper, &mut buf, &mut parts) | |
1475 | } else { | |
1476 | flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, *num, sign, | |
1477 | (0, 0), upper, &mut buf, &mut parts) | |
9346a6ac | 1478 | }; |
d9579d0f | 1479 | fmt.pad_formatted_parts(&formatted) |
9346a6ac AL |
1480 | } |
1481 | ||
1a4d82fc JJ |
1482 | macro_rules! floating { ($ty:ident) => { |
1483 | ||
85aaf69f SL |
1484 | #[stable(feature = "rust1", since = "1.0.0")] |
1485 | impl Debug for $ty { | |
1a4d82fc | 1486 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
d9579d0f | 1487 | float_to_decimal_common(fmt, self, true) |
1a4d82fc JJ |
1488 | } |
1489 | } | |
1490 | ||
85aaf69f SL |
1491 | #[stable(feature = "rust1", since = "1.0.0")] |
1492 | impl Display for $ty { | |
1a4d82fc | 1493 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
d9579d0f | 1494 | float_to_decimal_common(fmt, self, false) |
1a4d82fc JJ |
1495 | } |
1496 | } | |
1497 | ||
85aaf69f | 1498 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1499 | impl LowerExp for $ty { |
1500 | fn fmt(&self, fmt: &mut Formatter) -> Result { | |
d9579d0f | 1501 | float_to_exponential_common(fmt, self, false) |
1a4d82fc JJ |
1502 | } |
1503 | } | |
1504 | ||
85aaf69f | 1505 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1506 | impl UpperExp for $ty { |
1507 | fn fmt(&self, fmt: &mut Formatter) -> Result { | |
d9579d0f | 1508 | float_to_exponential_common(fmt, self, true) |
1a4d82fc JJ |
1509 | } |
1510 | } | |
1511 | } } | |
1512 | floating! { f32 } | |
1513 | floating! { f64 } | |
1514 | ||
85aaf69f | 1515 | // Implementation of Display/Debug for various core types |
1a4d82fc | 1516 | |
85aaf69f SL |
1517 | #[stable(feature = "rust1", since = "1.0.0")] |
1518 | impl<T> Debug for *const T { | |
1a4d82fc JJ |
1519 | fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } |
1520 | } | |
85aaf69f SL |
1521 | #[stable(feature = "rust1", since = "1.0.0")] |
1522 | impl<T> Debug for *mut T { | |
1a4d82fc JJ |
1523 | fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } |
1524 | } | |
1525 | ||
1526 | macro_rules! peel { | |
1527 | ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) | |
1528 | } | |
1529 | ||
1530 | macro_rules! tuple { | |
1531 | () => (); | |
1532 | ( $($name:ident,)+ ) => ( | |
85aaf69f SL |
1533 | #[stable(feature = "rust1", since = "1.0.0")] |
1534 | impl<$($name:Debug),*> Debug for ($($name,)*) { | |
1a4d82fc JJ |
1535 | #[allow(non_snake_case, unused_assignments)] |
1536 | fn fmt(&self, f: &mut Formatter) -> Result { | |
c1a9b12d | 1537 | let mut builder = f.debug_tuple(""); |
1a4d82fc | 1538 | let ($(ref $name,)*) = *self; |
85aaf69f | 1539 | let mut n = 0; |
1a4d82fc | 1540 | $( |
c1a9b12d | 1541 | builder.field($name); |
1a4d82fc JJ |
1542 | n += 1; |
1543 | )* | |
c1a9b12d | 1544 | |
1a4d82fc | 1545 | if n == 1 { |
c1a9b12d | 1546 | try!(write!(builder.formatter(), ",")); |
1a4d82fc | 1547 | } |
c1a9b12d SL |
1548 | |
1549 | builder.finish() | |
1a4d82fc JJ |
1550 | } |
1551 | } | |
1552 | peel! { $($name,)* } | |
1553 | ) | |
1554 | } | |
1555 | ||
1556 | tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } | |
1557 | ||
85aaf69f SL |
1558 | #[stable(feature = "rust1", since = "1.0.0")] |
1559 | impl<T: Debug> Debug for [T] { | |
1a4d82fc | 1560 | fn fmt(&self, f: &mut Formatter) -> Result { |
62682a34 | 1561 | f.debug_list().entries(self.iter()).finish() |
1a4d82fc JJ |
1562 | } |
1563 | } | |
1564 | ||
85aaf69f SL |
1565 | #[stable(feature = "rust1", since = "1.0.0")] |
1566 | impl Debug for () { | |
1a4d82fc JJ |
1567 | fn fmt(&self, f: &mut Formatter) -> Result { |
1568 | f.pad("()") | |
1569 | } | |
1570 | } | |
92a42be0 | 1571 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 1572 | impl<T> Debug for PhantomData<T> { |
1a4d82fc | 1573 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1574 | f.pad("PhantomData") |
1a4d82fc JJ |
1575 | } |
1576 | } | |
1577 | ||
85aaf69f SL |
1578 | #[stable(feature = "rust1", since = "1.0.0")] |
1579 | impl<T: Copy + Debug> Debug for Cell<T> { | |
1a4d82fc | 1580 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1581 | write!(f, "Cell {{ value: {:?} }}", self.get()) |
1a4d82fc JJ |
1582 | } |
1583 | } | |
1584 | ||
85aaf69f | 1585 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 1586 | impl<T: ?Sized + Debug> Debug for RefCell<T> { |
1a4d82fc | 1587 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f SL |
1588 | match self.borrow_state() { |
1589 | BorrowState::Unused | BorrowState::Reading => { | |
1590 | write!(f, "RefCell {{ value: {:?} }}", self.borrow()) | |
1591 | } | |
1592 | BorrowState::Writing => write!(f, "RefCell {{ <borrowed> }}"), | |
1593 | } | |
1a4d82fc JJ |
1594 | } |
1595 | } | |
1596 | ||
85aaf69f | 1597 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 1598 | impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> { |
1a4d82fc | 1599 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1600 | Debug::fmt(&**self, f) |
1a4d82fc JJ |
1601 | } |
1602 | } | |
1603 | ||
85aaf69f | 1604 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 1605 | impl<'b, T: ?Sized + Debug> Debug for RefMut<'b, T> { |
1a4d82fc | 1606 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1607 | Debug::fmt(&*(self.deref()), f) |
1a4d82fc JJ |
1608 | } |
1609 | } | |
1610 | ||
1611 | // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, | |
1612 | // it's a lot easier than creating all of the rt::Piece structures here. |