]>
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 | ||
54a0048b | 11 | //! Utilities for formatting and printing strings. |
1a4d82fc | 12 | |
85aaf69f | 13 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 14 | |
476ff2be | 15 | use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut}; |
9346a6ac | 16 | use marker::PhantomData; |
1a4d82fc | 17 | use mem; |
d9579d0f | 18 | use num::flt2dec; |
9346a6ac | 19 | use ops::Deref; |
1a4d82fc | 20 | use result; |
1a4d82fc | 21 | use slice; |
9346a6ac | 22 | use str; |
54a0048b | 23 | |
8bb4bdeb XL |
24 | mod float; |
25 | mod num; | |
26 | mod builders; | |
27 | ||
94b46f34 | 28 | #[stable(feature = "fmt_flags_align", since = "1.28.0")] |
54a0048b SL |
29 | /// Possible alignments returned by `Formatter::align` |
30 | #[derive(Debug)] | |
31 | pub enum Alignment { | |
94b46f34 | 32 | #[stable(feature = "fmt_flags_align", since = "1.28.0")] |
54a0048b SL |
33 | /// Indication that contents should be left-aligned. |
34 | Left, | |
94b46f34 | 35 | #[stable(feature = "fmt_flags_align", since = "1.28.0")] |
54a0048b SL |
36 | /// Indication that contents should be right-aligned. |
37 | Right, | |
94b46f34 | 38 | #[stable(feature = "fmt_flags_align", since = "1.28.0")] |
54a0048b SL |
39 | /// Indication that contents should be center-aligned. |
40 | Center, | |
54a0048b SL |
41 | } |
42 | ||
92a42be0 | 43 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
44 | pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; |
45 | ||
e9174d1e SL |
46 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
47 | issue = "0")] | |
85aaf69f SL |
48 | #[doc(hidden)] |
49 | pub mod rt { | |
50 | pub mod v1; | |
51 | } | |
52 | ||
1a4d82fc | 53 | /// The type returned by formatter methods. |
cc61c64b XL |
54 | /// |
55 | /// # Examples | |
56 | /// | |
57 | /// ``` | |
58 | /// use std::fmt; | |
59 | /// | |
60 | /// #[derive(Debug)] | |
61 | /// struct Triangle { | |
62 | /// a: f32, | |
63 | /// b: f32, | |
64 | /// c: f32 | |
65 | /// } | |
66 | /// | |
67 | /// impl fmt::Display for Triangle { | |
68 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
69 | /// write!(f, "({}, {}, {})", self.a, self.b, self.c) | |
70 | /// } | |
71 | /// } | |
72 | /// | |
73 | /// let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 }; | |
74 | /// | |
75 | /// println!("{}", pythagorean_triple); | |
76 | /// ``` | |
77 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
78 | pub type Result = result::Result<(), Error>; |
79 | ||
80 | /// The error type which is returned from formatting a message into a stream. | |
81 | /// | |
82 | /// This type does not support transmission of an error other than that an error | |
83 | /// occurred. Any extra information must be arranged to be transmitted through | |
84 | /// some other means. | |
3b2f2976 XL |
85 | /// |
86 | /// An important thing to remember is that the type `fmt::Error` should not be | |
2c00a5a8 | 87 | /// confused with [`std::io::Error`] or [`std::error::Error`], which you may also |
3b2f2976 XL |
88 | /// have in scope. |
89 | /// | |
2c00a5a8 XL |
90 | /// [`std::io::Error`]: ../../std/io/struct.Error.html |
91 | /// [`std::error::Error`]: ../../std/error/trait.Error.html | |
92 | /// | |
3b2f2976 XL |
93 | /// # Examples |
94 | /// | |
95 | /// ```rust | |
96 | /// use std::fmt::{self, write}; | |
97 | /// | |
98 | /// let mut output = String::new(); | |
99 | /// match write(&mut output, format_args!("Hello {}!", "world")) { | |
100 | /// Err(fmt::Error) => panic!("An error occurred"), | |
101 | /// _ => (), | |
102 | /// } | |
103 | /// ``` | |
85aaf69f | 104 | #[stable(feature = "rust1", since = "1.0.0")] |
a7813a04 | 105 | #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] |
1a4d82fc JJ |
106 | pub struct Error; |
107 | ||
108 | /// A collection of methods that are required to format a message into a stream. | |
109 | /// | |
110 | /// This trait is the type which this modules requires when formatting | |
8bb4bdeb | 111 | /// information. This is similar to the standard library's [`io::Write`] trait, |
1a4d82fc JJ |
112 | /// but it is only intended for use in libcore. |
113 | /// | |
114 | /// This trait should generally not be implemented by consumers of the standard | |
8bb4bdeb XL |
115 | /// library. The [`write!`] macro accepts an instance of [`io::Write`], and the |
116 | /// [`io::Write`] trait is favored over implementing this trait. | |
117 | /// | |
118 | /// [`write!`]: ../../std/macro.write.html | |
119 | /// [`io::Write`]: ../../std/io/trait.Write.html | |
85aaf69f SL |
120 | #[stable(feature = "rust1", since = "1.0.0")] |
121 | pub trait Write { | |
1a4d82fc JJ |
122 | /// Writes a slice of bytes into this writer, returning whether the write |
123 | /// succeeded. | |
124 | /// | |
125 | /// This method can only succeed if the entire byte slice was successfully | |
126 | /// written, and this method will not return until all data has been | |
127 | /// written or an error occurs. | |
128 | /// | |
129 | /// # Errors | |
130 | /// | |
8bb4bdeb XL |
131 | /// This function will return an instance of [`Error`] on error. |
132 | /// | |
133 | /// [`Error`]: struct.Error.html | |
134 | /// | |
135 | /// # Examples | |
136 | /// | |
137 | /// ``` | |
138 | /// use std::fmt::{Error, Write}; | |
139 | /// | |
140 | /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> { | |
141 | /// f.write_str(s) | |
142 | /// } | |
143 | /// | |
144 | /// let mut buf = String::new(); | |
145 | /// writer(&mut buf, "hola").unwrap(); | |
146 | /// assert_eq!(&buf, "hola"); | |
147 | /// ``` | |
85aaf69f | 148 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
149 | fn write_str(&mut self, s: &str) -> Result; |
150 | ||
8bb4bdeb | 151 | /// Writes a [`char`] into this writer, returning whether the write succeeded. |
d9579d0f | 152 | /// |
8bb4bdeb | 153 | /// A single [`char`] may be encoded as more than one byte. |
d9579d0f AL |
154 | /// This method can only succeed if the entire byte sequence was successfully |
155 | /// written, and this method will not return until all data has been | |
156 | /// written or an error occurs. | |
157 | /// | |
158 | /// # Errors | |
159 | /// | |
8bb4bdeb XL |
160 | /// This function will return an instance of [`Error`] on error. |
161 | /// | |
162 | /// [`char`]: ../../std/primitive.char.html | |
163 | /// [`Error`]: struct.Error.html | |
164 | /// | |
165 | /// # Examples | |
166 | /// | |
167 | /// ``` | |
168 | /// use std::fmt::{Error, Write}; | |
169 | /// | |
170 | /// fn writer<W: Write>(f: &mut W, c: char) -> Result<(), Error> { | |
171 | /// f.write_char(c) | |
172 | /// } | |
173 | /// | |
174 | /// let mut buf = String::new(); | |
175 | /// writer(&mut buf, 'a').unwrap(); | |
176 | /// writer(&mut buf, 'b').unwrap(); | |
177 | /// assert_eq!(&buf, "ab"); | |
178 | /// ``` | |
d9579d0f AL |
179 | #[stable(feature = "fmt_write_char", since = "1.1.0")] |
180 | fn write_char(&mut self, c: char) -> Result { | |
c30ab7b3 | 181 | self.write_str(c.encode_utf8(&mut [0; 4])) |
d9579d0f AL |
182 | } |
183 | ||
8bb4bdeb | 184 | /// Glue for usage of the [`write!`] macro with implementors of this trait. |
1a4d82fc JJ |
185 | /// |
186 | /// This method should generally not be invoked manually, but rather through | |
8bb4bdeb XL |
187 | /// the [`write!`] macro itself. |
188 | /// | |
189 | /// [`write!`]: ../../std/macro.write.html | |
190 | /// | |
191 | /// # Examples | |
192 | /// | |
193 | /// ``` | |
194 | /// use std::fmt::{Error, Write}; | |
195 | /// | |
196 | /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> { | |
197 | /// f.write_fmt(format_args!("{}", s)) | |
198 | /// } | |
199 | /// | |
200 | /// let mut buf = String::new(); | |
201 | /// writer(&mut buf, "world").unwrap(); | |
202 | /// assert_eq!(&buf, "world"); | |
203 | /// ``` | |
85aaf69f | 204 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
205 | fn write_fmt(&mut self, args: Arguments) -> Result { |
206 | // This Adapter is needed to allow `self` (of type `&mut | |
85aaf69f | 207 | // Self`) to be cast to a Write (below) without |
1a4d82fc JJ |
208 | // requiring a `Sized` bound. |
209 | struct Adapter<'a,T: ?Sized +'a>(&'a mut T); | |
210 | ||
85aaf69f SL |
211 | impl<'a, T: ?Sized> Write for Adapter<'a, T> |
212 | where T: Write | |
1a4d82fc JJ |
213 | { |
214 | fn write_str(&mut self, s: &str) -> Result { | |
215 | self.0.write_str(s) | |
216 | } | |
217 | ||
7453a54e SL |
218 | fn write_char(&mut self, c: char) -> Result { |
219 | self.0.write_char(c) | |
220 | } | |
221 | ||
1a4d82fc JJ |
222 | fn write_fmt(&mut self, args: Arguments) -> Result { |
223 | self.0.write_fmt(args) | |
224 | } | |
225 | } | |
226 | ||
227 | write(&mut Adapter(self), args) | |
228 | } | |
229 | } | |
230 | ||
e9174d1e SL |
231 | #[stable(feature = "fmt_write_blanket_impl", since = "1.4.0")] |
232 | impl<'a, W: Write + ?Sized> Write for &'a mut W { | |
233 | fn write_str(&mut self, s: &str) -> Result { | |
234 | (**self).write_str(s) | |
235 | } | |
236 | ||
237 | fn write_char(&mut self, c: char) -> Result { | |
238 | (**self).write_char(c) | |
239 | } | |
240 | ||
241 | fn write_fmt(&mut self, args: Arguments) -> Result { | |
242 | (**self).write_fmt(args) | |
243 | } | |
244 | } | |
245 | ||
1a4d82fc JJ |
246 | /// A struct to represent both where to emit formatting strings to and how they |
247 | /// should be formatted. A mutable version of this is passed to all formatting | |
248 | /// traits. | |
54a0048b | 249 | #[allow(missing_debug_implementations)] |
85aaf69f | 250 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 251 | pub struct Formatter<'a> { |
c34b1796 | 252 | flags: u32, |
1a4d82fc | 253 | fill: char, |
85aaf69f | 254 | align: rt::v1::Alignment, |
c34b1796 AL |
255 | width: Option<usize>, |
256 | precision: Option<usize>, | |
1a4d82fc | 257 | |
8faf50e0 | 258 | buf: &'a mut (dyn Write+'a), |
85aaf69f SL |
259 | curarg: slice::Iter<'a, ArgumentV1<'a>>, |
260 | args: &'a [ArgumentV1<'a>], | |
1a4d82fc JJ |
261 | } |
262 | ||
263 | // NB. Argument is essentially an optimized partially applied formatting function, | |
264 | // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`. | |
265 | ||
476ff2be SL |
266 | struct Void { |
267 | _priv: (), | |
ff7c6d11 XL |
268 | /// Erases all oibits, because `Void` erases the type of the object that |
269 | /// will be used to produce formatted output. Since we do not know what | |
270 | /// oibits the real types have (and they can have any or none), we need to | |
271 | /// take the most conservative approach and forbid all oibits. | |
272 | /// | |
273 | /// It was added after #45197 showed that one could share a `!Sync` | |
274 | /// object across threads by passing it into `format_args!`. | |
8faf50e0 | 275 | _oibit_remover: PhantomData<*mut dyn Fn()>, |
476ff2be | 276 | } |
1a4d82fc JJ |
277 | |
278 | /// This struct represents the generic "argument" which is taken by the Xprintf | |
279 | /// family of functions. It contains a function to format the given value. At | |
280 | /// compile time it is ensured that the function and the value have the correct | |
281 | /// types, and then this struct is used to canonicalize arguments to one type. | |
1a4d82fc | 282 | #[derive(Copy)] |
54a0048b | 283 | #[allow(missing_debug_implementations)] |
e9174d1e SL |
284 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
285 | issue = "0")] | |
85aaf69f SL |
286 | #[doc(hidden)] |
287 | pub struct ArgumentV1<'a> { | |
1a4d82fc JJ |
288 | value: &'a Void, |
289 | formatter: fn(&Void, &mut Formatter) -> Result, | |
290 | } | |
291 | ||
92a42be0 SL |
292 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
293 | issue = "0")] | |
c34b1796 AL |
294 | impl<'a> Clone for ArgumentV1<'a> { |
295 | fn clone(&self) -> ArgumentV1<'a> { | |
296 | *self | |
297 | } | |
298 | } | |
299 | ||
85aaf69f | 300 | impl<'a> ArgumentV1<'a> { |
1a4d82fc | 301 | #[inline(never)] |
c34b1796 | 302 | fn show_usize(x: &usize, f: &mut Formatter) -> Result { |
85aaf69f | 303 | Display::fmt(x, f) |
1a4d82fc JJ |
304 | } |
305 | ||
85aaf69f | 306 | #[doc(hidden)] |
e9174d1e SL |
307 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
308 | issue = "0")] | |
85aaf69f SL |
309 | pub fn new<'b, T>(x: &'b T, |
310 | f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { | |
1a4d82fc | 311 | unsafe { |
85aaf69f | 312 | ArgumentV1 { |
1a4d82fc JJ |
313 | formatter: mem::transmute(f), |
314 | value: mem::transmute(x) | |
315 | } | |
316 | } | |
317 | } | |
318 | ||
85aaf69f | 319 | #[doc(hidden)] |
e9174d1e SL |
320 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
321 | issue = "0")] | |
c34b1796 AL |
322 | pub fn from_usize(x: &usize) -> ArgumentV1 { |
323 | ArgumentV1::new(x, ArgumentV1::show_usize) | |
1a4d82fc JJ |
324 | } |
325 | ||
c34b1796 AL |
326 | fn as_usize(&self) -> Option<usize> { |
327 | if self.formatter as usize == ArgumentV1::show_usize as usize { | |
328 | Some(unsafe { *(self.value as *const _ as *const usize) }) | |
1a4d82fc JJ |
329 | } else { |
330 | None | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
85aaf69f | 335 | // flags available in the v1 format of format_args |
c34b1796 | 336 | #[derive(Copy, Clone)] |
0531ce1d | 337 | enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex } |
85aaf69f | 338 | |
1a4d82fc JJ |
339 | impl<'a> Arguments<'a> { |
340 | /// When using the format_args!() macro, this function is used to generate the | |
341 | /// Arguments structure. | |
342 | #[doc(hidden)] #[inline] | |
e9174d1e SL |
343 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
344 | issue = "0")] | |
85aaf69f SL |
345 | pub fn new_v1(pieces: &'a [&'a str], |
346 | args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { | |
1a4d82fc | 347 | Arguments { |
3b2f2976 | 348 | pieces, |
1a4d82fc | 349 | fmt: None, |
3b2f2976 | 350 | args, |
1a4d82fc JJ |
351 | } |
352 | } | |
353 | ||
354 | /// This function is used to specify nonstandard formatting parameters. | |
355 | /// The `pieces` array must be at least as long as `fmt` to construct | |
356 | /// a valid Arguments structure. Also, any `Count` within `fmt` that is | |
357 | /// `CountIsParam` or `CountIsNextParam` has to point to an argument | |
c34b1796 | 358 | /// created with `argumentusize`. However, failing to do so doesn't cause |
1a4d82fc JJ |
359 | /// unsafety, but will ignore invalid . |
360 | #[doc(hidden)] #[inline] | |
e9174d1e SL |
361 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", |
362 | issue = "0")] | |
85aaf69f SL |
363 | pub fn new_v1_formatted(pieces: &'a [&'a str], |
364 | args: &'a [ArgumentV1<'a>], | |
365 | fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { | |
1a4d82fc | 366 | Arguments { |
3b2f2976 | 367 | pieces, |
1a4d82fc | 368 | fmt: Some(fmt), |
3b2f2976 | 369 | args, |
1a4d82fc JJ |
370 | } |
371 | } | |
8bb4bdeb XL |
372 | |
373 | /// Estimates the length of the formatted text. | |
374 | /// | |
375 | /// This is intended to be used for setting initial `String` capacity | |
376 | /// when using `format!`. Note: this is neither the lower nor upper bound. | |
377 | #[doc(hidden)] #[inline] | |
378 | #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
379 | issue = "0")] | |
380 | pub fn estimated_capacity(&self) -> usize { | |
381 | let pieces_length: usize = self.pieces.iter() | |
382 | .map(|x| x.len()).sum(); | |
383 | ||
384 | if self.args.is_empty() { | |
385 | pieces_length | |
386 | } else if self.pieces[0] == "" && pieces_length < 16 { | |
387 | // If the format string starts with an argument, | |
388 | // don't preallocate anything, unless length | |
389 | // of pieces is significant. | |
390 | 0 | |
391 | } else { | |
392 | // There are some arguments, so any additional push | |
393 | // will reallocate the string. To avoid that, | |
394 | // we're "pre-doubling" the capacity here. | |
395 | pieces_length.checked_mul(2).unwrap_or(0) | |
396 | } | |
397 | } | |
1a4d82fc JJ |
398 | } |
399 | ||
400 | /// This structure represents a safely precompiled version of a format string | |
401 | /// and its arguments. This cannot be generated at runtime because it cannot | |
8bb4bdeb | 402 | /// safely be done, so no constructors are given and the fields are private |
1a4d82fc JJ |
403 | /// to prevent modification. |
404 | /// | |
83c7162d XL |
405 | /// The [`format_args!`] macro will safely create an instance of this structure. |
406 | /// The macro validates the format string at compile-time so usage of the | |
407 | /// [`write`] and [`format`] functions can be safely performed. | |
9e0c209e | 408 | /// |
0531ce1d XL |
409 | /// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` |
410 | /// and `Display` contexts as seen below. The example also shows that `Debug` | |
411 | /// and `Display` format to the same thing: the interpolated format string | |
412 | /// in `format_args!`. | |
413 | /// | |
414 | /// ```rust | |
83c7162d XL |
415 | /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); |
416 | /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); | |
0531ce1d XL |
417 | /// assert_eq!("1 foo 2", display); |
418 | /// assert_eq!(display, debug); | |
419 | /// ``` | |
420 | /// | |
9e0c209e SL |
421 | /// [`format_args!`]: ../../std/macro.format_args.html |
422 | /// [`format`]: ../../std/fmt/fn.format.html | |
423 | /// [`write`]: ../../std/fmt/fn.write.html | |
85aaf69f | 424 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 425 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
426 | pub struct Arguments<'a> { |
427 | // Format string pieces to print. | |
428 | pieces: &'a [&'a str], | |
429 | ||
430 | // Placeholder specs, or `None` if all specs are default (as in "{}{}"). | |
85aaf69f | 431 | fmt: Option<&'a [rt::v1::Argument]>, |
1a4d82fc JJ |
432 | |
433 | // Dynamic arguments for interpolation, to be interleaved with string | |
434 | // pieces. (Every argument is preceded by a string piece.) | |
85aaf69f | 435 | args: &'a [ArgumentV1<'a>], |
1a4d82fc JJ |
436 | } |
437 | ||
85aaf69f SL |
438 | #[stable(feature = "rust1", since = "1.0.0")] |
439 | impl<'a> Debug for Arguments<'a> { | |
1a4d82fc | 440 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
85aaf69f | 441 | Display::fmt(self, fmt) |
1a4d82fc JJ |
442 | } |
443 | } | |
444 | ||
85aaf69f SL |
445 | #[stable(feature = "rust1", since = "1.0.0")] |
446 | impl<'a> Display for Arguments<'a> { | |
1a4d82fc JJ |
447 | fn fmt(&self, fmt: &mut Formatter) -> Result { |
448 | write(fmt.buf, *self) | |
449 | } | |
450 | } | |
451 | ||
ea8adc8c | 452 | /// `?` formatting. |
c1a9b12d SL |
453 | /// |
454 | /// `Debug` should format the output in a programmer-facing, debugging context. | |
62682a34 SL |
455 | /// |
456 | /// Generally speaking, you should just `derive` a `Debug` implementation. | |
457 | /// | |
c1a9b12d SL |
458 | /// When used with the alternate format specifier `#?`, the output is pretty-printed. |
459 | /// | |
460 | /// For more information on formatters, see [the module-level documentation][module]. | |
461 | /// | |
b039eaaf | 462 | /// [module]: ../../std/fmt/index.html |
c1a9b12d | 463 | /// |
3157f602 XL |
464 | /// This trait can be used with `#[derive]` if all fields implement `Debug`. When |
465 | /// `derive`d for structs, it will use the name of the `struct`, then `{`, then a | |
466 | /// comma-separated list of each field's name and `Debug` value, then `}`. For | |
467 | /// `enum`s, it will use the name of the variant and, if applicable, `(`, then the | |
468 | /// `Debug` values of the fields, then `)`. | |
92a42be0 | 469 | /// |
62682a34 SL |
470 | /// # Examples |
471 | /// | |
472 | /// Deriving an implementation: | |
473 | /// | |
474 | /// ``` | |
475 | /// #[derive(Debug)] | |
476 | /// struct Point { | |
477 | /// x: i32, | |
478 | /// y: i32, | |
479 | /// } | |
480 | /// | |
481 | /// let origin = Point { x: 0, y: 0 }; | |
482 | /// | |
483 | /// println!("The origin is: {:?}", origin); | |
484 | /// ``` | |
485 | /// | |
486 | /// Manually implementing: | |
487 | /// | |
488 | /// ``` | |
489 | /// use std::fmt; | |
490 | /// | |
491 | /// struct Point { | |
492 | /// x: i32, | |
493 | /// y: i32, | |
494 | /// } | |
495 | /// | |
496 | /// impl fmt::Debug for Point { | |
497 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
92a42be0 | 498 | /// write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) |
62682a34 SL |
499 | /// } |
500 | /// } | |
501 | /// | |
502 | /// let origin = Point { x: 0, y: 0 }; | |
503 | /// | |
504 | /// println!("The origin is: {:?}", origin); | |
505 | /// ``` | |
506 | /// | |
c1a9b12d SL |
507 | /// This outputs: |
508 | /// | |
509 | /// ```text | |
510 | /// The origin is: Point { x: 0, y: 0 } | |
511 | /// ``` | |
512 | /// | |
ea8adc8c | 513 | /// There are a number of `debug_*` methods on [`Formatter`] to help you with manual |
62682a34 SL |
514 | /// implementations, such as [`debug_struct`][debug_struct]. |
515 | /// | |
c1a9b12d | 516 | /// `Debug` implementations using either `derive` or the debug builder API |
ea8adc8c | 517 | /// on [`Formatter`] support pretty printing using the alternate flag: `{:#?}`. |
c1a9b12d | 518 | /// |
9cc50fc6 | 519 | /// [debug_struct]: ../../std/fmt/struct.Formatter.html#method.debug_struct |
ea8adc8c | 520 | /// [`Formatter`]: ../../std/fmt/struct.Formatter.html |
c1a9b12d SL |
521 | /// |
522 | /// Pretty printing with `#?`: | |
523 | /// | |
524 | /// ``` | |
525 | /// #[derive(Debug)] | |
526 | /// struct Point { | |
527 | /// x: i32, | |
528 | /// y: i32, | |
529 | /// } | |
530 | /// | |
531 | /// let origin = Point { x: 0, y: 0 }; | |
532 | /// | |
533 | /// println!("The origin is: {:#?}", origin); | |
534 | /// ``` | |
535 | /// | |
536 | /// This outputs: | |
537 | /// | |
538 | /// ```text | |
539 | /// The origin is: Point { | |
540 | /// x: 0, | |
541 | /// y: 0 | |
542 | /// } | |
543 | /// ``` | |
85aaf69f | 544 | #[stable(feature = "rust1", since = "1.0.0")] |
2c00a5a8 | 545 | #[rustc_on_unimplemented( |
83c7162d XL |
546 | on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`", |
547 | note="add `#[derive(Debug)]` or manually implement `{Debug}`"), | |
2c00a5a8 | 548 | message="`{Self}` doesn't implement `{Debug}`", |
83c7162d | 549 | label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", |
2c00a5a8 | 550 | )] |
83c7162d | 551 | #[doc(alias = "{:?}")] |
85aaf69f SL |
552 | #[lang = "debug_trait"] |
553 | pub trait Debug { | |
554 | /// Formats the value using the given formatter. | |
abe05a73 XL |
555 | /// |
556 | /// # Examples | |
557 | /// | |
558 | /// ``` | |
559 | /// use std::fmt; | |
560 | /// | |
561 | /// struct Position { | |
562 | /// longitude: f32, | |
563 | /// latitude: f32, | |
564 | /// } | |
565 | /// | |
566 | /// impl fmt::Debug for Position { | |
567 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
568 | /// write!(f, "({:?}, {:?})", self.longitude, self.latitude) | |
569 | /// } | |
570 | /// } | |
571 | /// | |
572 | /// assert_eq!("(1.987, 2.983)".to_owned(), | |
573 | /// format!("{:?}", Position { longitude: 1.987, latitude: 2.983, })); | |
574 | /// ``` | |
85aaf69f | 575 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 576 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
577 | } |
578 | ||
c1a9b12d SL |
579 | /// Format trait for an empty format, `{}`. |
580 | /// | |
581 | /// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing | |
582 | /// output, and so cannot be derived. | |
583 | /// | |
584 | /// [debug]: trait.Debug.html | |
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 | /// Implementing `Display` on a type: | |
593 | /// | |
594 | /// ``` | |
595 | /// use std::fmt; | |
596 | /// | |
597 | /// struct Point { | |
598 | /// x: i32, | |
599 | /// y: i32, | |
600 | /// } | |
601 | /// | |
602 | /// impl fmt::Display for Point { | |
603 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
604 | /// write!(f, "({}, {})", self.x, self.y) | |
605 | /// } | |
606 | /// } | |
607 | /// | |
608 | /// let origin = Point { x: 0, y: 0 }; | |
609 | /// | |
610 | /// println!("The origin is: {}", origin); | |
611 | /// ``` | |
2c00a5a8 XL |
612 | #[rustc_on_unimplemented( |
613 | message="`{Self}` doesn't implement `{Display}`", | |
83c7162d XL |
614 | label="`{Self}` cannot be formatted with the default formatter", |
615 | note="in format strings you may be able to use `{{:?}}` \ | |
616 | (or {{:#?}} for pretty-print) instead", | |
2c00a5a8 | 617 | )] |
83c7162d | 618 | #[doc(alias = "{}")] |
85aaf69f SL |
619 | #[stable(feature = "rust1", since = "1.0.0")] |
620 | pub trait Display { | |
621 | /// Formats the value using the given formatter. | |
8bb4bdeb XL |
622 | /// |
623 | /// # Examples | |
624 | /// | |
625 | /// ``` | |
626 | /// use std::fmt; | |
627 | /// | |
628 | /// struct Position { | |
629 | /// longitude: f32, | |
630 | /// latitude: f32, | |
631 | /// } | |
632 | /// | |
633 | /// impl fmt::Display for Position { | |
634 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
635 | /// write!(f, "({}, {})", self.longitude, self.latitude) | |
636 | /// } | |
637 | /// } | |
638 | /// | |
639 | /// assert_eq!("(1.987, 2.983)".to_owned(), | |
640 | /// format!("{}", Position { longitude: 1.987, latitude: 2.983, })); | |
641 | /// ``` | |
85aaf69f | 642 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 643 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
644 | } |
645 | ||
ea8adc8c | 646 | /// `o` formatting. |
c1a9b12d SL |
647 | /// |
648 | /// The `Octal` trait should format its output as a number in base-8. | |
649 | /// | |
ff7c6d11 XL |
650 | /// For primitive signed integers (`i8` to `i128`, and `isize`), |
651 | /// negative values are formatted as the two’s complement representation. | |
652 | /// | |
c1a9b12d SL |
653 | /// The alternate flag, `#`, adds a `0o` in front of the output. |
654 | /// | |
655 | /// For more information on formatters, see [the module-level documentation][module]. | |
656 | /// | |
b039eaaf | 657 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
658 | /// |
659 | /// # Examples | |
660 | /// | |
661 | /// Basic usage with `i32`: | |
662 | /// | |
663 | /// ``` | |
664 | /// let x = 42; // 42 is '52' in octal | |
665 | /// | |
666 | /// assert_eq!(format!("{:o}", x), "52"); | |
667 | /// assert_eq!(format!("{:#o}", x), "0o52"); | |
ff7c6d11 XL |
668 | /// |
669 | /// assert_eq!(format!("{:o}", -16), "37777777760"); | |
c1a9b12d SL |
670 | /// ``` |
671 | /// | |
672 | /// Implementing `Octal` on a type: | |
673 | /// | |
674 | /// ``` | |
675 | /// use std::fmt; | |
676 | /// | |
677 | /// struct Length(i32); | |
678 | /// | |
679 | /// impl fmt::Octal for Length { | |
680 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
681 | /// let val = self.0; | |
682 | /// | |
683 | /// write!(f, "{:o}", val) // delegate to i32's implementation | |
684 | /// } | |
685 | /// } | |
686 | /// | |
687 | /// let l = Length(9); | |
688 | /// | |
689 | /// println!("l as octal is: {:o}", l); | |
690 | /// ``` | |
85aaf69f | 691 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
692 | pub trait Octal { |
693 | /// Formats the value using the given formatter. | |
85aaf69f | 694 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 695 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
696 | } |
697 | ||
ea8adc8c | 698 | /// `b` formatting. |
c1a9b12d SL |
699 | /// |
700 | /// The `Binary` trait should format its output as a number in binary. | |
701 | /// | |
0531ce1d | 702 | /// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]), |
ff7c6d11 XL |
703 | /// negative values are formatted as the two’s complement representation. |
704 | /// | |
c1a9b12d SL |
705 | /// The alternate flag, `#`, adds a `0b` in front of the output. |
706 | /// | |
707 | /// For more information on formatters, see [the module-level documentation][module]. | |
708 | /// | |
c1a9b12d SL |
709 | /// # Examples |
710 | /// | |
0531ce1d | 711 | /// Basic usage with [`i32`]: |
c1a9b12d SL |
712 | /// |
713 | /// ``` | |
714 | /// let x = 42; // 42 is '101010' in binary | |
715 | /// | |
716 | /// assert_eq!(format!("{:b}", x), "101010"); | |
717 | /// assert_eq!(format!("{:#b}", x), "0b101010"); | |
ff7c6d11 XL |
718 | /// |
719 | /// assert_eq!(format!("{:b}", -16), "11111111111111111111111111110000"); | |
c1a9b12d SL |
720 | /// ``` |
721 | /// | |
722 | /// Implementing `Binary` on a type: | |
723 | /// | |
724 | /// ``` | |
725 | /// use std::fmt; | |
726 | /// | |
727 | /// struct Length(i32); | |
728 | /// | |
729 | /// impl fmt::Binary for Length { | |
730 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
731 | /// let val = self.0; | |
732 | /// | |
733 | /// write!(f, "{:b}", val) // delegate to i32's implementation | |
734 | /// } | |
735 | /// } | |
736 | /// | |
737 | /// let l = Length(107); | |
738 | /// | |
739 | /// println!("l as binary is: {:b}", l); | |
740 | /// ``` | |
0531ce1d XL |
741 | /// |
742 | /// [module]: ../../std/fmt/index.html | |
743 | /// [`i8`]: ../../std/primitive.i8.html | |
744 | /// [`i128`]: ../../std/primitive.i128.html | |
745 | /// [`isize`]: ../../std/primitive.isize.html | |
746 | /// [`i32`]: ../../std/primitive.i32.html | |
85aaf69f | 747 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
748 | pub trait Binary { |
749 | /// Formats the value using the given formatter. | |
85aaf69f | 750 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 751 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
752 | } |
753 | ||
ea8adc8c | 754 | /// `x` formatting. |
c1a9b12d | 755 | /// |
b039eaaf | 756 | /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` |
c1a9b12d SL |
757 | /// in lower case. |
758 | /// | |
ff7c6d11 XL |
759 | /// For primitive signed integers (`i8` to `i128`, and `isize`), |
760 | /// negative values are formatted as the two’s complement representation. | |
761 | /// | |
c1a9b12d SL |
762 | /// The alternate flag, `#`, adds a `0x` in front of the output. |
763 | /// | |
764 | /// For more information on formatters, see [the module-level documentation][module]. | |
765 | /// | |
b039eaaf | 766 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
767 | /// |
768 | /// # Examples | |
769 | /// | |
770 | /// Basic usage with `i32`: | |
771 | /// | |
772 | /// ``` | |
773 | /// let x = 42; // 42 is '2a' in hex | |
774 | /// | |
775 | /// assert_eq!(format!("{:x}", x), "2a"); | |
776 | /// assert_eq!(format!("{:#x}", x), "0x2a"); | |
ff7c6d11 XL |
777 | /// |
778 | /// assert_eq!(format!("{:x}", -16), "fffffff0"); | |
c1a9b12d SL |
779 | /// ``` |
780 | /// | |
781 | /// Implementing `LowerHex` on a type: | |
782 | /// | |
783 | /// ``` | |
784 | /// use std::fmt; | |
785 | /// | |
786 | /// struct Length(i32); | |
787 | /// | |
788 | /// impl fmt::LowerHex for Length { | |
789 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
790 | /// let val = self.0; | |
791 | /// | |
792 | /// write!(f, "{:x}", val) // delegate to i32's implementation | |
793 | /// } | |
794 | /// } | |
795 | /// | |
796 | /// let l = Length(9); | |
797 | /// | |
798 | /// println!("l as hex is: {:x}", l); | |
799 | /// ``` | |
85aaf69f | 800 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
801 | pub trait LowerHex { |
802 | /// Formats the value using the given formatter. | |
85aaf69f | 803 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 804 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
805 | } |
806 | ||
ea8adc8c | 807 | /// `X` formatting. |
c1a9b12d | 808 | /// |
b039eaaf | 809 | /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` |
c1a9b12d SL |
810 | /// in upper case. |
811 | /// | |
ff7c6d11 XL |
812 | /// For primitive signed integers (`i8` to `i128`, and `isize`), |
813 | /// negative values are formatted as the two’s complement representation. | |
814 | /// | |
c1a9b12d SL |
815 | /// The alternate flag, `#`, adds a `0x` in front of the output. |
816 | /// | |
817 | /// For more information on formatters, see [the module-level documentation][module]. | |
818 | /// | |
b039eaaf | 819 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
820 | /// |
821 | /// # Examples | |
822 | /// | |
823 | /// Basic usage with `i32`: | |
824 | /// | |
825 | /// ``` | |
826 | /// let x = 42; // 42 is '2A' in hex | |
827 | /// | |
828 | /// assert_eq!(format!("{:X}", x), "2A"); | |
829 | /// assert_eq!(format!("{:#X}", x), "0x2A"); | |
ff7c6d11 XL |
830 | /// |
831 | /// assert_eq!(format!("{:X}", -16), "FFFFFFF0"); | |
c1a9b12d SL |
832 | /// ``` |
833 | /// | |
834 | /// Implementing `UpperHex` on a type: | |
835 | /// | |
836 | /// ``` | |
837 | /// use std::fmt; | |
838 | /// | |
839 | /// struct Length(i32); | |
840 | /// | |
841 | /// impl fmt::UpperHex for Length { | |
842 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
843 | /// let val = self.0; | |
844 | /// | |
845 | /// write!(f, "{:X}", val) // delegate to i32's implementation | |
846 | /// } | |
847 | /// } | |
848 | /// | |
849 | /// let l = Length(9); | |
850 | /// | |
851 | /// println!("l as hex is: {:X}", l); | |
852 | /// ``` | |
85aaf69f | 853 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
854 | pub trait UpperHex { |
855 | /// Formats the value using the given formatter. | |
85aaf69f | 856 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 857 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
858 | } |
859 | ||
ea8adc8c | 860 | /// `p` formatting. |
c1a9b12d SL |
861 | /// |
862 | /// The `Pointer` trait should format its output as a memory location. This is commonly presented | |
b039eaaf | 863 | /// as hexadecimal. |
c1a9b12d SL |
864 | /// |
865 | /// For more information on formatters, see [the module-level documentation][module]. | |
866 | /// | |
b039eaaf | 867 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
868 | /// |
869 | /// # Examples | |
870 | /// | |
871 | /// Basic usage with `&i32`: | |
872 | /// | |
873 | /// ``` | |
874 | /// let x = &42; | |
875 | /// | |
876 | /// let address = format!("{:p}", x); // this produces something like '0x7f06092ac6d0' | |
877 | /// ``` | |
878 | /// | |
879 | /// Implementing `Pointer` on a type: | |
880 | /// | |
881 | /// ``` | |
882 | /// use std::fmt; | |
883 | /// | |
884 | /// struct Length(i32); | |
885 | /// | |
886 | /// impl fmt::Pointer for Length { | |
887 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
888 | /// // use `as` to convert to a `*const T`, which implements Pointer, which we can use | |
889 | /// | |
890 | /// write!(f, "{:p}", self as *const Length) | |
891 | /// } | |
892 | /// } | |
893 | /// | |
894 | /// let l = Length(42); | |
895 | /// | |
896 | /// println!("l is in memory here: {:p}", l); | |
897 | /// ``` | |
85aaf69f | 898 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
899 | pub trait Pointer { |
900 | /// Formats the value using the given formatter. | |
85aaf69f | 901 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 902 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
903 | } |
904 | ||
ea8adc8c | 905 | /// `e` formatting. |
c1a9b12d SL |
906 | /// |
907 | /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. | |
908 | /// | |
909 | /// For more information on formatters, see [the module-level documentation][module]. | |
910 | /// | |
b039eaaf | 911 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
912 | /// |
913 | /// # Examples | |
914 | /// | |
915 | /// Basic usage with `i32`: | |
916 | /// | |
917 | /// ``` | |
918 | /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation | |
919 | /// | |
920 | /// assert_eq!(format!("{:e}", x), "4.2e1"); | |
921 | /// ``` | |
922 | /// | |
923 | /// Implementing `LowerExp` on a type: | |
924 | /// | |
925 | /// ``` | |
926 | /// use std::fmt; | |
927 | /// | |
928 | /// struct Length(i32); | |
929 | /// | |
930 | /// impl fmt::LowerExp for Length { | |
931 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
932 | /// let val = self.0; | |
933 | /// write!(f, "{}e1", val / 10) | |
934 | /// } | |
935 | /// } | |
936 | /// | |
937 | /// let l = Length(100); | |
938 | /// | |
939 | /// println!("l in scientific notation is: {:e}", l); | |
940 | /// ``` | |
85aaf69f | 941 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
942 | pub trait LowerExp { |
943 | /// Formats the value using the given formatter. | |
85aaf69f | 944 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 945 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
946 | } |
947 | ||
ea8adc8c | 948 | /// `E` formatting. |
c1a9b12d SL |
949 | /// |
950 | /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. | |
951 | /// | |
952 | /// For more information on formatters, see [the module-level documentation][module]. | |
953 | /// | |
b039eaaf | 954 | /// [module]: ../../std/fmt/index.html |
c1a9b12d SL |
955 | /// |
956 | /// # Examples | |
957 | /// | |
958 | /// Basic usage with `f32`: | |
959 | /// | |
960 | /// ``` | |
961 | /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation | |
962 | /// | |
963 | /// assert_eq!(format!("{:E}", x), "4.2E1"); | |
964 | /// ``` | |
965 | /// | |
966 | /// Implementing `UpperExp` on a type: | |
967 | /// | |
968 | /// ``` | |
969 | /// use std::fmt; | |
970 | /// | |
971 | /// struct Length(i32); | |
972 | /// | |
973 | /// impl fmt::UpperExp for Length { | |
974 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
975 | /// let val = self.0; | |
976 | /// write!(f, "{}E1", val / 10) | |
977 | /// } | |
978 | /// } | |
979 | /// | |
980 | /// let l = Length(100); | |
981 | /// | |
982 | /// println!("l in scientific notation is: {:E}", l); | |
983 | /// ``` | |
85aaf69f | 984 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
985 | pub trait UpperExp { |
986 | /// Formats the value using the given formatter. | |
85aaf69f | 987 | #[stable(feature = "rust1", since = "1.0.0")] |
8bb4bdeb | 988 | fn fmt(&self, f: &mut Formatter) -> Result; |
1a4d82fc JJ |
989 | } |
990 | ||
041b39d2 XL |
991 | /// The `write` function takes an output stream, and an `Arguments` struct |
992 | /// that can be precompiled with the `format_args!` macro. | |
1a4d82fc | 993 | /// |
041b39d2 XL |
994 | /// The arguments will be formatted according to the specified format string |
995 | /// into the output stream provided. | |
a7813a04 XL |
996 | /// |
997 | /// # Examples | |
998 | /// | |
999 | /// Basic usage: | |
1000 | /// | |
1001 | /// ``` | |
1002 | /// use std::fmt; | |
1003 | /// | |
1004 | /// let mut output = String::new(); | |
1005 | /// fmt::write(&mut output, format_args!("Hello {}!", "world")) | |
1006 | /// .expect("Error occurred while trying to write in String"); | |
1007 | /// assert_eq!(output, "Hello world!"); | |
1008 | /// ``` | |
1009 | /// | |
ff7c6d11 | 1010 | /// Please note that using [`write!`] might be preferable. Example: |
a7813a04 XL |
1011 | /// |
1012 | /// ``` | |
1013 | /// use std::fmt::Write; | |
1014 | /// | |
1015 | /// let mut output = String::new(); | |
1016 | /// write!(&mut output, "Hello {}!", "world") | |
1017 | /// .expect("Error occurred while trying to write in String"); | |
1018 | /// assert_eq!(output, "Hello world!"); | |
1019 | /// ``` | |
1020 | /// | |
c30ab7b3 | 1021 | /// [`write!`]: ../../std/macro.write.html |
85aaf69f | 1022 | #[stable(feature = "rust1", since = "1.0.0")] |
8faf50e0 | 1023 | pub fn write(output: &mut dyn Write, args: Arguments) -> Result { |
1a4d82fc JJ |
1024 | let mut formatter = Formatter { |
1025 | flags: 0, | |
1026 | width: None, | |
1027 | precision: None, | |
1028 | buf: output, | |
54a0048b | 1029 | align: rt::v1::Alignment::Unknown, |
1a4d82fc JJ |
1030 | fill: ' ', |
1031 | args: args.args, | |
1032 | curarg: args.args.iter(), | |
1033 | }; | |
1034 | ||
1035 | let mut pieces = args.pieces.iter(); | |
1036 | ||
1037 | match args.fmt { | |
1038 | None => { | |
1039 | // We can use default formatting parameters for all arguments. | |
1040 | for (arg, piece) in args.args.iter().zip(pieces.by_ref()) { | |
54a0048b SL |
1041 | formatter.buf.write_str(*piece)?; |
1042 | (arg.formatter)(arg.value, &mut formatter)?; | |
1a4d82fc JJ |
1043 | } |
1044 | } | |
1045 | Some(fmt) => { | |
1046 | // Every spec has a corresponding argument that is preceded by | |
1047 | // a string piece. | |
1048 | for (arg, piece) in fmt.iter().zip(pieces.by_ref()) { | |
54a0048b SL |
1049 | formatter.buf.write_str(*piece)?; |
1050 | formatter.run(arg)?; | |
1a4d82fc JJ |
1051 | } |
1052 | } | |
1053 | } | |
1054 | ||
1055 | // There can be only one trailing string piece left. | |
3157f602 XL |
1056 | if let Some(piece) = pieces.next() { |
1057 | formatter.buf.write_str(*piece)?; | |
1a4d82fc JJ |
1058 | } |
1059 | ||
1060 | Ok(()) | |
1061 | } | |
1062 | ||
1063 | impl<'a> Formatter<'a> { | |
ff7c6d11 | 1064 | fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> |
8faf50e0 | 1065 | where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c) |
ff7c6d11 XL |
1066 | { |
1067 | Formatter { | |
1068 | // We want to change this | |
1069 | buf: wrap(self.buf), | |
1070 | ||
1071 | // And preserve these | |
1072 | flags: self.flags, | |
1073 | fill: self.fill, | |
1074 | align: self.align, | |
1075 | width: self.width, | |
1076 | precision: self.precision, | |
1077 | ||
1078 | // These only exist in the struct for the `run` method, | |
1079 | // which won’t be used together with this method. | |
1080 | curarg: self.curarg.clone(), | |
1081 | args: self.args, | |
1082 | } | |
1083 | } | |
1084 | ||
1a4d82fc JJ |
1085 | // First up is the collection of functions used to execute a format string |
1086 | // at runtime. This consumes all of the compile-time statics generated by | |
1087 | // the format! syntax extension. | |
85aaf69f | 1088 | fn run(&mut self, arg: &rt::v1::Argument) -> Result { |
1a4d82fc JJ |
1089 | // Fill in the format parameters into the formatter |
1090 | self.fill = arg.format.fill; | |
1091 | self.align = arg.format.align; | |
1092 | self.flags = arg.format.flags; | |
1093 | self.width = self.getcount(&arg.format.width); | |
1094 | self.precision = self.getcount(&arg.format.precision); | |
1095 | ||
1096 | // Extract the correct argument | |
1097 | let value = match arg.position { | |
85aaf69f SL |
1098 | rt::v1::Position::Next => { *self.curarg.next().unwrap() } |
1099 | rt::v1::Position::At(i) => self.args[i], | |
1a4d82fc JJ |
1100 | }; |
1101 | ||
1102 | // Then actually do some printing | |
1103 | (value.formatter)(value.value, self) | |
1104 | } | |
1105 | ||
c34b1796 | 1106 | fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> { |
1a4d82fc | 1107 | match *cnt { |
85aaf69f SL |
1108 | rt::v1::Count::Is(n) => Some(n), |
1109 | rt::v1::Count::Implied => None, | |
1110 | rt::v1::Count::Param(i) => { | |
c34b1796 | 1111 | self.args[i].as_usize() |
1a4d82fc | 1112 | } |
85aaf69f | 1113 | rt::v1::Count::NextParam => { |
c34b1796 | 1114 | self.curarg.next().and_then(|arg| arg.as_usize()) |
1a4d82fc JJ |
1115 | } |
1116 | } | |
1117 | } | |
1118 | ||
1119 | // Helper methods used for padding and processing formatting arguments that | |
1120 | // all formatting traits can use. | |
1121 | ||
1122 | /// Performs the correct padding for an integer which has already been | |
85aaf69f SL |
1123 | /// emitted into a str. The str should *not* contain the sign for the |
1124 | /// integer, that will be added by this method. | |
1a4d82fc JJ |
1125 | /// |
1126 | /// # Arguments | |
1127 | /// | |
9cc50fc6 | 1128 | /// * is_nonnegative - whether the original integer was either positive or zero. |
c34b1796 | 1129 | /// * prefix - if the '#' character (Alternate) is provided, this |
1a4d82fc JJ |
1130 | /// is the prefix to put in front of the number. |
1131 | /// * buf - the byte array that the number has been formatted into | |
1132 | /// | |
1133 | /// This function will correctly account for the flags provided as well as | |
1134 | /// the minimum width. It will not take precision into account. | |
b7449926 XL |
1135 | /// |
1136 | /// # Examples | |
1137 | /// | |
1138 | /// ``` | |
1139 | /// use std::fmt; | |
1140 | /// | |
1141 | /// struct Foo { nb: i32 }; | |
1142 | /// | |
1143 | /// impl Foo { | |
1144 | /// fn new(nb: i32) -> Foo { | |
1145 | /// Foo { | |
1146 | /// nb, | |
1147 | /// } | |
1148 | /// } | |
1149 | /// } | |
1150 | /// | |
1151 | /// impl fmt::Display for Foo { | |
1152 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1153 | /// // We need to remove "-" from the number output. | |
1154 | /// let tmp = self.nb.abs().to_string(); | |
1155 | /// | |
1156 | /// formatter.pad_integral(self.nb > 0, "Foo ", &tmp) | |
1157 | /// } | |
1158 | /// } | |
1159 | /// | |
1160 | /// assert_eq!(&format!("{}", Foo::new(2)), "2"); | |
1161 | /// assert_eq!(&format!("{}", Foo::new(-1)), "-1"); | |
1162 | /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1"); | |
1163 | /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); | |
1164 | /// ``` | |
85aaf69f | 1165 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 1166 | pub fn pad_integral(&mut self, |
9cc50fc6 | 1167 | is_nonnegative: bool, |
1a4d82fc JJ |
1168 | prefix: &str, |
1169 | buf: &str) | |
1170 | -> Result { | |
1a4d82fc JJ |
1171 | let mut width = buf.len(); |
1172 | ||
1173 | let mut sign = None; | |
9cc50fc6 | 1174 | if !is_nonnegative { |
1a4d82fc | 1175 | sign = Some('-'); width += 1; |
b039eaaf | 1176 | } else if self.sign_plus() { |
1a4d82fc JJ |
1177 | sign = Some('+'); width += 1; |
1178 | } | |
1179 | ||
1180 | let mut prefixed = false; | |
b039eaaf | 1181 | if self.alternate() { |
92a42be0 | 1182 | prefixed = true; width += prefix.chars().count(); |
1a4d82fc JJ |
1183 | } |
1184 | ||
1185 | // Writes the sign if it exists, and then the prefix if it was requested | |
85aaf69f SL |
1186 | let write_prefix = |f: &mut Formatter| { |
1187 | if let Some(c) = sign { | |
c30ab7b3 | 1188 | f.buf.write_str(c.encode_utf8(&mut [0; 4]))?; |
1a4d82fc JJ |
1189 | } |
1190 | if prefixed { f.buf.write_str(prefix) } | |
1191 | else { Ok(()) } | |
1192 | }; | |
1193 | ||
1194 | // The `width` field is more of a `min-width` parameter at this point. | |
1195 | match self.width { | |
1196 | // If there's no minimum length requirements then we can just | |
1197 | // write the bytes. | |
1198 | None => { | |
54a0048b | 1199 | write_prefix(self)?; self.buf.write_str(buf) |
1a4d82fc JJ |
1200 | } |
1201 | // Check if we're over the minimum width, if so then we can also | |
1202 | // just write the bytes. | |
1203 | Some(min) if width >= min => { | |
54a0048b | 1204 | write_prefix(self)?; self.buf.write_str(buf) |
1a4d82fc JJ |
1205 | } |
1206 | // The sign and prefix goes before the padding if the fill character | |
1207 | // is zero | |
b039eaaf | 1208 | Some(min) if self.sign_aware_zero_pad() => { |
1a4d82fc | 1209 | self.fill = '0'; |
cc61c64b | 1210 | self.align = rt::v1::Alignment::Right; |
54a0048b SL |
1211 | write_prefix(self)?; |
1212 | self.with_padding(min - width, rt::v1::Alignment::Right, |f| { | |
1a4d82fc JJ |
1213 | f.buf.write_str(buf) |
1214 | }) | |
1215 | } | |
1216 | // Otherwise, the sign and prefix goes after the padding | |
1217 | Some(min) => { | |
54a0048b SL |
1218 | self.with_padding(min - width, rt::v1::Alignment::Right, |f| { |
1219 | write_prefix(f)?; f.buf.write_str(buf) | |
1a4d82fc JJ |
1220 | }) |
1221 | } | |
1222 | } | |
1223 | } | |
1224 | ||
1225 | /// This function takes a string slice and emits it to the internal buffer | |
1226 | /// after applying the relevant formatting flags specified. The flags | |
1227 | /// recognized for generic strings are: | |
1228 | /// | |
1229 | /// * width - the minimum width of what to emit | |
1230 | /// * fill/align - what to emit and where to emit it if the string | |
1231 | /// provided needs to be padded | |
1232 | /// * precision - the maximum length to emit, the string is truncated if it | |
1233 | /// is longer than this length | |
1234 | /// | |
8bb4bdeb | 1235 | /// Notably this function ignores the `flag` parameters. |
94b46f34 XL |
1236 | /// |
1237 | /// # Examples | |
1238 | /// | |
1239 | /// ``` | |
1240 | /// use std::fmt; | |
1241 | /// | |
1242 | /// struct Foo; | |
1243 | /// | |
1244 | /// impl fmt::Display for Foo { | |
1245 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1246 | /// formatter.pad("Foo") | |
1247 | /// } | |
1248 | /// } | |
1249 | /// | |
1250 | /// assert_eq!(&format!("{:<4}", Foo), "Foo "); | |
1251 | /// assert_eq!(&format!("{:0>4}", Foo), "0Foo"); | |
1252 | /// ``` | |
85aaf69f | 1253 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1254 | pub fn pad(&mut self, s: &str) -> Result { |
1255 | // Make sure there's a fast path up front | |
1256 | if self.width.is_none() && self.precision.is_none() { | |
1257 | return self.buf.write_str(s); | |
1258 | } | |
1259 | // The `precision` field can be interpreted as a `max-width` for the | |
5bcae85e SL |
1260 | // string being formatted. |
1261 | let s = if let Some(max) = self.precision { | |
1262 | // If our string is longer that the precision, then we must have | |
1263 | // truncation. However other flags like `fill`, `width` and `align` | |
1264 | // must act as always. | |
b7449926 | 1265 | if let Some((i, _)) = s.char_indices().nth(max) { |
83c7162d XL |
1266 | // LLVM here can't prove that `..i` won't panic `&s[..i]`, but |
1267 | // we know that it can't panic. Use `get` + `unwrap_or` to avoid | |
1268 | // `unsafe` and otherwise don't emit any panic-related code | |
1269 | // here. | |
1270 | s.get(..i).unwrap_or(&s) | |
5bcae85e SL |
1271 | } else { |
1272 | &s | |
1a4d82fc | 1273 | } |
5bcae85e SL |
1274 | } else { |
1275 | &s | |
1276 | }; | |
1a4d82fc JJ |
1277 | // The `width` field is more of a `min-width` parameter at this point. |
1278 | match self.width { | |
1279 | // If we're under the maximum length, and there's no minimum length | |
1280 | // requirements, then we can just emit the string | |
1281 | None => self.buf.write_str(s), | |
1282 | // If we're under the maximum width, check if we're over the minimum | |
1283 | // width, if so it's as easy as just emitting the string. | |
92a42be0 | 1284 | Some(width) if s.chars().count() >= width => { |
1a4d82fc JJ |
1285 | self.buf.write_str(s) |
1286 | } | |
1287 | // If we're under both the maximum and the minimum width, then fill | |
1288 | // up the minimum width with the specified string + some alignment. | |
1289 | Some(width) => { | |
54a0048b SL |
1290 | let align = rt::v1::Alignment::Left; |
1291 | self.with_padding(width - s.chars().count(), align, |me| { | |
1a4d82fc JJ |
1292 | me.buf.write_str(s) |
1293 | }) | |
1294 | } | |
1295 | } | |
1296 | } | |
1297 | ||
1298 | /// Runs a callback, emitting the correct padding either before or | |
1299 | /// afterwards depending on whether right or left alignment is requested. | |
54a0048b | 1300 | fn with_padding<F>(&mut self, padding: usize, default: rt::v1::Alignment, |
85aaf69f SL |
1301 | f: F) -> Result |
1302 | where F: FnOnce(&mut Formatter) -> Result, | |
1a4d82fc | 1303 | { |
1a4d82fc | 1304 | let align = match self.align { |
54a0048b | 1305 | rt::v1::Alignment::Unknown => default, |
1a4d82fc JJ |
1306 | _ => self.align |
1307 | }; | |
1308 | ||
1309 | let (pre_pad, post_pad) = match align { | |
54a0048b SL |
1310 | rt::v1::Alignment::Left => (0, padding), |
1311 | rt::v1::Alignment::Right | | |
1312 | rt::v1::Alignment::Unknown => (padding, 0), | |
1313 | rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), | |
1a4d82fc JJ |
1314 | }; |
1315 | ||
c30ab7b3 SL |
1316 | let mut fill = [0; 4]; |
1317 | let fill = self.fill.encode_utf8(&mut fill); | |
1a4d82fc | 1318 | |
85aaf69f | 1319 | for _ in 0..pre_pad { |
54a0048b | 1320 | self.buf.write_str(fill)?; |
1a4d82fc JJ |
1321 | } |
1322 | ||
54a0048b | 1323 | f(self)?; |
1a4d82fc | 1324 | |
85aaf69f | 1325 | for _ in 0..post_pad { |
54a0048b | 1326 | self.buf.write_str(fill)?; |
1a4d82fc JJ |
1327 | } |
1328 | ||
1329 | Ok(()) | |
1330 | } | |
1331 | ||
d9579d0f AL |
1332 | /// Takes the formatted parts and applies the padding. |
1333 | /// Assumes that the caller already has rendered the parts with required precision, | |
1334 | /// so that `self.precision` can be ignored. | |
1335 | fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
1336 | if let Some(mut width) = self.width { | |
1337 | // for the sign-aware zero padding, we render the sign first and | |
1338 | // behave as if we had no sign from the beginning. | |
1339 | let mut formatted = formatted.clone(); | |
d9579d0f | 1340 | let old_fill = self.fill; |
cc61c64b XL |
1341 | let old_align = self.align; |
1342 | let mut align = old_align; | |
b039eaaf | 1343 | if self.sign_aware_zero_pad() { |
d9579d0f AL |
1344 | // a sign always goes first |
1345 | let sign = unsafe { str::from_utf8_unchecked(formatted.sign) }; | |
54a0048b | 1346 | self.buf.write_str(sign)?; |
d9579d0f AL |
1347 | |
1348 | // remove the sign from the formatted parts | |
1349 | formatted.sign = b""; | |
1350 | width = if width < sign.len() { 0 } else { width - sign.len() }; | |
54a0048b | 1351 | align = rt::v1::Alignment::Right; |
d9579d0f | 1352 | self.fill = '0'; |
cc61c64b | 1353 | self.align = rt::v1::Alignment::Right; |
d9579d0f AL |
1354 | } |
1355 | ||
1356 | // remaining parts go through the ordinary padding process. | |
1357 | let len = formatted.len(); | |
1358 | let ret = if width <= len { // no padding | |
1359 | self.write_formatted_parts(&formatted) | |
1360 | } else { | |
1361 | self.with_padding(width - len, align, |f| { | |
1362 | f.write_formatted_parts(&formatted) | |
1363 | }) | |
1364 | }; | |
1365 | self.fill = old_fill; | |
cc61c64b | 1366 | self.align = old_align; |
d9579d0f AL |
1367 | ret |
1368 | } else { | |
1369 | // this is the common case and we take a shortcut | |
1370 | self.write_formatted_parts(formatted) | |
1371 | } | |
1372 | } | |
1373 | ||
1374 | fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
8faf50e0 | 1375 | fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { |
d9579d0f AL |
1376 | buf.write_str(unsafe { str::from_utf8_unchecked(s) }) |
1377 | } | |
1378 | ||
1379 | if !formatted.sign.is_empty() { | |
54a0048b | 1380 | write_bytes(self.buf, formatted.sign)?; |
d9579d0f AL |
1381 | } |
1382 | for part in formatted.parts { | |
1383 | match *part { | |
1384 | flt2dec::Part::Zero(mut nzeroes) => { | |
1385 | const ZEROES: &'static str = // 64 zeroes | |
1386 | "0000000000000000000000000000000000000000000000000000000000000000"; | |
1387 | while nzeroes > ZEROES.len() { | |
54a0048b | 1388 | self.buf.write_str(ZEROES)?; |
d9579d0f AL |
1389 | nzeroes -= ZEROES.len(); |
1390 | } | |
1391 | if nzeroes > 0 { | |
54a0048b | 1392 | self.buf.write_str(&ZEROES[..nzeroes])?; |
d9579d0f AL |
1393 | } |
1394 | } | |
1395 | flt2dec::Part::Num(mut v) => { | |
1396 | let mut s = [0; 5]; | |
1397 | let len = part.len(); | |
1398 | for c in s[..len].iter_mut().rev() { | |
1399 | *c = b'0' + (v % 10) as u8; | |
1400 | v /= 10; | |
1401 | } | |
54a0048b | 1402 | write_bytes(self.buf, &s[..len])?; |
d9579d0f AL |
1403 | } |
1404 | flt2dec::Part::Copy(buf) => { | |
54a0048b | 1405 | write_bytes(self.buf, buf)?; |
d9579d0f AL |
1406 | } |
1407 | } | |
1408 | } | |
1409 | Ok(()) | |
1410 | } | |
1411 | ||
1a4d82fc JJ |
1412 | /// Writes some data to the underlying buffer contained within this |
1413 | /// formatter. | |
b7449926 XL |
1414 | /// |
1415 | /// # Examples | |
1416 | /// | |
1417 | /// ``` | |
1418 | /// use std::fmt; | |
1419 | /// | |
1420 | /// struct Foo; | |
1421 | /// | |
1422 | /// impl fmt::Display for Foo { | |
1423 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1424 | /// formatter.write_str("Foo") | |
1425 | /// // This is equivalent to: | |
1426 | /// // write!(formatter, "Foo") | |
1427 | /// } | |
1428 | /// } | |
1429 | /// | |
1430 | /// assert_eq!(&format!("{}", Foo), "Foo"); | |
1431 | /// assert_eq!(&format!("{:0>8}", Foo), "Foo"); | |
1432 | /// ``` | |
85aaf69f | 1433 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1434 | pub fn write_str(&mut self, data: &str) -> Result { |
1435 | self.buf.write_str(data) | |
1436 | } | |
1437 | ||
94b46f34 | 1438 | /// Writes some formatted information into this instance. |
b7449926 XL |
1439 | /// |
1440 | /// # Examples | |
1441 | /// | |
1442 | /// ``` | |
1443 | /// use std::fmt; | |
1444 | /// | |
1445 | /// struct Foo(i32); | |
1446 | /// | |
1447 | /// impl fmt::Display for Foo { | |
1448 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1449 | /// formatter.write_fmt(format_args!("Foo {}", self.0)) | |
1450 | /// } | |
1451 | /// } | |
1452 | /// | |
1453 | /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1"); | |
1454 | /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2"); | |
1455 | /// ``` | |
85aaf69f | 1456 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1457 | pub fn write_fmt(&mut self, fmt: Arguments) -> Result { |
1458 | write(self.buf, fmt) | |
1459 | } | |
1460 | ||
ea8adc8c | 1461 | /// Flags for formatting |
85aaf69f | 1462 | #[stable(feature = "rust1", since = "1.0.0")] |
ff7c6d11 XL |
1463 | #[rustc_deprecated(since = "1.24.0", |
1464 | reason = "use the `sign_plus`, `sign_minus`, `alternate`, \ | |
1465 | or `sign_aware_zero_pad` methods instead")] | |
c34b1796 | 1466 | pub fn flags(&self) -> u32 { self.flags } |
1a4d82fc | 1467 | |
94b46f34 XL |
1468 | /// Character used as 'fill' whenever there is alignment. |
1469 | /// | |
1470 | /// # Examples | |
1471 | /// | |
1472 | /// ``` | |
1473 | /// use std::fmt; | |
1474 | /// | |
1475 | /// struct Foo; | |
1476 | /// | |
1477 | /// impl fmt::Display for Foo { | |
1478 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1479 | /// let c = formatter.fill(); | |
1480 | /// if let Some(width) = formatter.width() { | |
1481 | /// for _ in 0..width { | |
1482 | /// write!(formatter, "{}", c)?; | |
1483 | /// } | |
1484 | /// Ok(()) | |
1485 | /// } else { | |
1486 | /// write!(formatter, "{}", c) | |
1487 | /// } | |
1488 | /// } | |
1489 | /// } | |
1490 | /// | |
1491 | /// // We set alignment to the left with ">". | |
1492 | /// assert_eq!(&format!("{:G>3}", Foo), "GGG"); | |
1493 | /// assert_eq!(&format!("{:t>6}", Foo), "tttttt"); | |
1494 | /// ``` | |
b039eaaf | 1495 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1a4d82fc JJ |
1496 | pub fn fill(&self) -> char { self.fill } |
1497 | ||
94b46f34 XL |
1498 | /// Flag indicating what form of alignment was requested. |
1499 | /// | |
1500 | /// # Examples | |
1501 | /// | |
1502 | /// ``` | |
1503 | /// extern crate core; | |
1504 | /// | |
1505 | /// use std::fmt::{self, Alignment}; | |
1506 | /// | |
1507 | /// struct Foo; | |
1508 | /// | |
1509 | /// impl fmt::Display for Foo { | |
1510 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1511 | /// let s = if let Some(s) = formatter.align() { | |
1512 | /// match s { | |
1513 | /// Alignment::Left => "left", | |
1514 | /// Alignment::Right => "right", | |
1515 | /// Alignment::Center => "center", | |
1516 | /// } | |
1517 | /// } else { | |
1518 | /// "into the void" | |
1519 | /// }; | |
1520 | /// write!(formatter, "{}", s) | |
1521 | /// } | |
1522 | /// } | |
1523 | /// | |
1524 | /// fn main() { | |
1525 | /// assert_eq!(&format!("{:<}", Foo), "left"); | |
1526 | /// assert_eq!(&format!("{:>}", Foo), "right"); | |
1527 | /// assert_eq!(&format!("{:^}", Foo), "center"); | |
1528 | /// assert_eq!(&format!("{}", Foo), "into the void"); | |
1529 | /// } | |
1530 | /// ``` | |
1531 | #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
1532 | pub fn align(&self) -> Option<Alignment> { | |
54a0048b | 1533 | match self.align { |
94b46f34 XL |
1534 | rt::v1::Alignment::Left => Some(Alignment::Left), |
1535 | rt::v1::Alignment::Right => Some(Alignment::Right), | |
1536 | rt::v1::Alignment::Center => Some(Alignment::Center), | |
1537 | rt::v1::Alignment::Unknown => None, | |
54a0048b SL |
1538 | } |
1539 | } | |
1a4d82fc | 1540 | |
0531ce1d XL |
1541 | /// Optionally specified integer width that the output should be. |
1542 | /// | |
1543 | /// # Examples | |
1544 | /// | |
1545 | /// ``` | |
1546 | /// use std::fmt; | |
1547 | /// | |
1548 | /// struct Foo(i32); | |
1549 | /// | |
1550 | /// impl fmt::Display for Foo { | |
1551 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1552 | /// if let Some(width) = formatter.width() { | |
1553 | /// // If we received a width, we use it | |
1554 | /// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width) | |
1555 | /// } else { | |
1556 | /// // Otherwise we do nothing special | |
1557 | /// write!(formatter, "Foo({})", self.0) | |
1558 | /// } | |
1559 | /// } | |
1560 | /// } | |
1561 | /// | |
1562 | /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) "); | |
1563 | /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
1564 | /// ``` | |
b039eaaf | 1565 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
c34b1796 | 1566 | pub fn width(&self) -> Option<usize> { self.width } |
1a4d82fc | 1567 | |
0531ce1d XL |
1568 | /// Optionally specified precision for numeric types. |
1569 | /// | |
1570 | /// # Examples | |
1571 | /// | |
1572 | /// ``` | |
1573 | /// use std::fmt; | |
1574 | /// | |
1575 | /// struct Foo(f32); | |
1576 | /// | |
1577 | /// impl fmt::Display for Foo { | |
1578 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1579 | /// if let Some(precision) = formatter.precision() { | |
1580 | /// // If we received a precision, we use it. | |
1581 | /// write!(formatter, "Foo({1:.*})", precision, self.0) | |
1582 | /// } else { | |
1583 | /// // Otherwise we default to 2. | |
1584 | /// write!(formatter, "Foo({:.2})", self.0) | |
1585 | /// } | |
1586 | /// } | |
1587 | /// } | |
1588 | /// | |
1589 | /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); | |
1590 | /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); | |
1591 | /// ``` | |
b039eaaf | 1592 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
c34b1796 AL |
1593 | pub fn precision(&self) -> Option<usize> { self.precision } |
1594 | ||
b039eaaf | 1595 | /// Determines if the `+` flag was specified. |
0531ce1d XL |
1596 | /// |
1597 | /// # Examples | |
1598 | /// | |
1599 | /// ``` | |
1600 | /// use std::fmt; | |
1601 | /// | |
1602 | /// struct Foo(i32); | |
1603 | /// | |
1604 | /// impl fmt::Display for Foo { | |
1605 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1606 | /// if formatter.sign_plus() { | |
1607 | /// write!(formatter, | |
1608 | /// "Foo({}{})", | |
1609 | /// if self.0 < 0 { '-' } else { '+' }, | |
1610 | /// self.0) | |
1611 | /// } else { | |
1612 | /// write!(formatter, "Foo({})", self.0) | |
1613 | /// } | |
1614 | /// } | |
1615 | /// } | |
1616 | /// | |
1617 | /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)"); | |
1618 | /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
1619 | /// ``` | |
b039eaaf SL |
1620 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1621 | pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 } | |
1622 | ||
1623 | /// Determines if the `-` flag was specified. | |
0531ce1d XL |
1624 | /// |
1625 | /// # Examples | |
1626 | /// | |
1627 | /// ``` | |
1628 | /// use std::fmt; | |
1629 | /// | |
1630 | /// struct Foo(i32); | |
1631 | /// | |
1632 | /// impl fmt::Display for Foo { | |
1633 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1634 | /// if formatter.sign_minus() { | |
1635 | /// // You want a minus sign? Have one! | |
1636 | /// write!(formatter, "-Foo({})", self.0) | |
1637 | /// } else { | |
1638 | /// write!(formatter, "Foo({})", self.0) | |
1639 | /// } | |
1640 | /// } | |
1641 | /// } | |
1642 | /// | |
1643 | /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)"); | |
1644 | /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
1645 | /// ``` | |
b039eaaf SL |
1646 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1647 | pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 } | |
1648 | ||
1649 | /// Determines if the `#` flag was specified. | |
0531ce1d XL |
1650 | /// |
1651 | /// # Examples | |
1652 | /// | |
1653 | /// ``` | |
1654 | /// use std::fmt; | |
1655 | /// | |
1656 | /// struct Foo(i32); | |
1657 | /// | |
1658 | /// impl fmt::Display for Foo { | |
1659 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1660 | /// if formatter.alternate() { | |
1661 | /// write!(formatter, "Foo({})", self.0) | |
1662 | /// } else { | |
1663 | /// write!(formatter, "{}", self.0) | |
1664 | /// } | |
1665 | /// } | |
1666 | /// } | |
1667 | /// | |
1668 | /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)"); | |
1669 | /// assert_eq!(&format!("{}", Foo(23)), "23"); | |
1670 | /// ``` | |
b039eaaf SL |
1671 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1672 | pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 } | |
1673 | ||
1674 | /// Determines if the `0` flag was specified. | |
0531ce1d XL |
1675 | /// |
1676 | /// # Examples | |
1677 | /// | |
1678 | /// ``` | |
1679 | /// use std::fmt; | |
1680 | /// | |
1681 | /// struct Foo(i32); | |
1682 | /// | |
1683 | /// impl fmt::Display for Foo { | |
1684 | /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
1685 | /// assert!(formatter.sign_aware_zero_pad()); | |
1686 | /// assert_eq!(formatter.width(), Some(4)); | |
1687 | /// // We ignore the formatter's options. | |
1688 | /// write!(formatter, "{}", self.0) | |
1689 | /// } | |
1690 | /// } | |
1691 | /// | |
1692 | /// assert_eq!(&format!("{:04}", Foo(23)), "23"); | |
1693 | /// ``` | |
b039eaaf SL |
1694 | #[stable(feature = "fmt_flags", since = "1.5.0")] |
1695 | pub fn sign_aware_zero_pad(&self) -> bool { | |
1696 | self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 | |
1697 | } | |
1698 | ||
0531ce1d XL |
1699 | // FIXME: Decide what public API we want for these two flags. |
1700 | // https://github.com/rust-lang/rust/issues/48584 | |
1701 | fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 } | |
1702 | ||
1703 | fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 } | |
1704 | ||
ea8adc8c XL |
1705 | /// Creates a [`DebugStruct`] builder designed to assist with creation of |
1706 | /// [`fmt::Debug`] implementations for structs. | |
1707 | /// | |
1708 | /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html | |
1709 | /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html | |
c34b1796 AL |
1710 | /// |
1711 | /// # Examples | |
1712 | /// | |
1713 | /// ```rust | |
c34b1796 | 1714 | /// use std::fmt; |
0531ce1d | 1715 | /// use std::net::Ipv4Addr; |
c34b1796 AL |
1716 | /// |
1717 | /// struct Foo { | |
1718 | /// bar: i32, | |
1719 | /// baz: String, | |
0531ce1d | 1720 | /// addr: Ipv4Addr, |
c34b1796 AL |
1721 | /// } |
1722 | /// | |
1723 | /// impl fmt::Debug for Foo { | |
1724 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1725 | /// fmt.debug_struct("Foo") | |
1726 | /// .field("bar", &self.bar) | |
1727 | /// .field("baz", &self.baz) | |
0531ce1d | 1728 | /// .field("addr", &format_args!("{}", self.addr)) |
c34b1796 AL |
1729 | /// .finish() |
1730 | /// } | |
1731 | /// } | |
1732 | /// | |
0531ce1d XL |
1733 | /// assert_eq!( |
1734 | /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", | |
1735 | /// format!("{:?}", Foo { | |
1736 | /// bar: 10, | |
1737 | /// baz: "Hello World".to_string(), | |
1738 | /// addr: Ipv4Addr::new(127, 0, 0, 1), | |
1739 | /// }) | |
1740 | /// ); | |
c34b1796 | 1741 | /// ``` |
62682a34 | 1742 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1743 | pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { |
1744 | builders::debug_struct_new(self, name) | |
1745 | } | |
1746 | ||
1747 | /// Creates a `DebugTuple` builder designed to assist with creation of | |
1748 | /// `fmt::Debug` implementations for tuple structs. | |
1749 | /// | |
1750 | /// # Examples | |
1751 | /// | |
1752 | /// ```rust | |
c34b1796 | 1753 | /// use std::fmt; |
0531ce1d | 1754 | /// use std::marker::PhantomData; |
c34b1796 | 1755 | /// |
0531ce1d | 1756 | /// struct Foo<T>(i32, String, PhantomData<T>); |
c34b1796 | 1757 | /// |
0531ce1d | 1758 | /// impl<T> fmt::Debug for Foo<T> { |
c34b1796 AL |
1759 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1760 | /// fmt.debug_tuple("Foo") | |
1761 | /// .field(&self.0) | |
1762 | /// .field(&self.1) | |
0531ce1d | 1763 | /// .field(&format_args!("_")) |
c34b1796 AL |
1764 | /// .finish() |
1765 | /// } | |
1766 | /// } | |
1767 | /// | |
0531ce1d XL |
1768 | /// assert_eq!( |
1769 | /// "Foo(10, \"Hello\", _)", | |
1770 | /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::<u8>)) | |
1771 | /// ); | |
c34b1796 | 1772 | /// ``` |
62682a34 | 1773 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1774 | pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { |
1775 | builders::debug_tuple_new(self, name) | |
1776 | } | |
1777 | ||
1778 | /// Creates a `DebugList` builder designed to assist with creation of | |
1779 | /// `fmt::Debug` implementations for list-like structures. | |
1780 | /// | |
1781 | /// # Examples | |
1782 | /// | |
1783 | /// ```rust | |
c34b1796 AL |
1784 | /// use std::fmt; |
1785 | /// | |
1786 | /// struct Foo(Vec<i32>); | |
1787 | /// | |
1788 | /// impl fmt::Debug for Foo { | |
1789 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1790 | /// fmt.debug_list().entries(self.0.iter()).finish() |
c34b1796 AL |
1791 | /// } |
1792 | /// } | |
1793 | /// | |
1794 | /// // prints "[10, 11]" | |
1795 | /// println!("{:?}", Foo(vec![10, 11])); | |
1796 | /// ``` | |
62682a34 | 1797 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1798 | pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { |
1799 | builders::debug_list_new(self) | |
1800 | } | |
1801 | ||
1802 | /// Creates a `DebugSet` builder designed to assist with creation of | |
1803 | /// `fmt::Debug` implementations for set-like structures. | |
1804 | /// | |
1805 | /// # Examples | |
1806 | /// | |
1807 | /// ```rust | |
c34b1796 AL |
1808 | /// use std::fmt; |
1809 | /// | |
1810 | /// struct Foo(Vec<i32>); | |
1811 | /// | |
1812 | /// impl fmt::Debug for Foo { | |
1813 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1814 | /// fmt.debug_set().entries(self.0.iter()).finish() |
c34b1796 AL |
1815 | /// } |
1816 | /// } | |
1817 | /// | |
1818 | /// // prints "{10, 11}" | |
1819 | /// println!("{:?}", Foo(vec![10, 11])); | |
1820 | /// ``` | |
0531ce1d XL |
1821 | /// |
1822 | /// [`format_args!`]: ../../std/macro.format_args.html | |
1823 | /// | |
1824 | /// In this more complex example, we use [`format_args!`] and `.debug_set()` | |
1825 | /// to build a list of match arms: | |
1826 | /// | |
1827 | /// ```rust | |
1828 | /// use std::fmt; | |
1829 | /// | |
1830 | /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); | |
1831 | /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); | |
1832 | /// | |
1833 | /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> | |
1834 | /// where | |
1835 | /// L: 'a + fmt::Debug, R: 'a + fmt::Debug | |
1836 | /// { | |
1837 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1838 | /// L::fmt(&(self.0).0, fmt)?; | |
1839 | /// fmt.write_str(" => ")?; | |
1840 | /// R::fmt(&(self.0).1, fmt) | |
1841 | /// } | |
1842 | /// } | |
1843 | /// | |
1844 | /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> | |
1845 | /// where | |
1846 | /// K: 'a + fmt::Debug, V: 'a + fmt::Debug | |
1847 | /// { | |
1848 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1849 | /// fmt.debug_set() | |
1850 | /// .entries(self.0.iter().map(Arm)) | |
1851 | /// .entry(&Arm(&(format_args!("_"), &self.1))) | |
1852 | /// .finish() | |
1853 | /// } | |
1854 | /// } | |
1855 | /// ``` | |
62682a34 | 1856 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1857 | pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { |
1858 | builders::debug_set_new(self) | |
1859 | } | |
1860 | ||
1861 | /// Creates a `DebugMap` builder designed to assist with creation of | |
1862 | /// `fmt::Debug` implementations for map-like structures. | |
1863 | /// | |
1864 | /// # Examples | |
1865 | /// | |
1866 | /// ```rust | |
c34b1796 AL |
1867 | /// use std::fmt; |
1868 | /// | |
1869 | /// struct Foo(Vec<(String, i32)>); | |
1870 | /// | |
1871 | /// impl fmt::Debug for Foo { | |
1872 | /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
62682a34 | 1873 | /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() |
c34b1796 AL |
1874 | /// } |
1875 | /// } | |
1876 | /// | |
1877 | /// // prints "{"A": 10, "B": 11}" | |
1878 | /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); | |
1879 | /// ``` | |
62682a34 | 1880 | #[stable(feature = "debug_builders", since = "1.2.0")] |
c34b1796 AL |
1881 | pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { |
1882 | builders::debug_map_new(self) | |
1883 | } | |
1a4d82fc JJ |
1884 | } |
1885 | ||
62682a34 SL |
1886 | #[stable(since = "1.2.0", feature = "formatter_write")] |
1887 | impl<'a> Write for Formatter<'a> { | |
1888 | fn write_str(&mut self, s: &str) -> Result { | |
1889 | self.buf.write_str(s) | |
1890 | } | |
1891 | ||
1892 | fn write_char(&mut self, c: char) -> Result { | |
1893 | self.buf.write_char(c) | |
1894 | } | |
1895 | ||
1896 | fn write_fmt(&mut self, args: Arguments) -> Result { | |
1897 | write(self.buf, args) | |
1898 | } | |
1899 | } | |
1900 | ||
85aaf69f SL |
1901 | #[stable(feature = "rust1", since = "1.0.0")] |
1902 | impl Display for Error { | |
1a4d82fc | 1903 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1904 | Display::fmt("an error occurred when formatting an argument", f) |
1a4d82fc JJ |
1905 | } |
1906 | } | |
1907 | ||
1a4d82fc JJ |
1908 | // Implementations of the core formatting traits |
1909 | ||
1910 | macro_rules! fmt_refs { | |
1911 | ($($tr:ident),*) => { | |
1912 | $( | |
85aaf69f | 1913 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1914 | impl<'a, T: ?Sized + $tr> $tr for &'a T { |
1915 | fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
1916 | } | |
85aaf69f | 1917 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
1918 | impl<'a, T: ?Sized + $tr> $tr for &'a mut T { |
1919 | fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
1920 | } | |
1921 | )* | |
1922 | } | |
1923 | } | |
1924 | ||
85aaf69f | 1925 | fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } |
1a4d82fc | 1926 | |
ff7c6d11 | 1927 | #[unstable(feature = "never_type", issue = "35121")] |
9e0c209e SL |
1928 | impl Debug for ! { |
1929 | fn fmt(&self, _: &mut Formatter) -> Result { | |
1930 | *self | |
5bcae85e SL |
1931 | } |
1932 | } | |
1933 | ||
ff7c6d11 | 1934 | #[unstable(feature = "never_type", issue = "35121")] |
9e0c209e SL |
1935 | impl Display for ! { |
1936 | fn fmt(&self, _: &mut Formatter) -> Result { | |
1937 | *self | |
1938 | } | |
1939 | } | |
5bcae85e | 1940 | |
85aaf69f SL |
1941 | #[stable(feature = "rust1", since = "1.0.0")] |
1942 | impl Debug for bool { | |
2c00a5a8 | 1943 | #[inline] |
1a4d82fc | 1944 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1945 | Display::fmt(self, f) |
1a4d82fc JJ |
1946 | } |
1947 | } | |
1948 | ||
85aaf69f SL |
1949 | #[stable(feature = "rust1", since = "1.0.0")] |
1950 | impl Display for bool { | |
1a4d82fc | 1951 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 1952 | Display::fmt(if *self { "true" } else { "false" }, f) |
1a4d82fc JJ |
1953 | } |
1954 | } | |
1955 | ||
85aaf69f SL |
1956 | #[stable(feature = "rust1", since = "1.0.0")] |
1957 | impl Debug for str { | |
1a4d82fc | 1958 | fn fmt(&self, f: &mut Formatter) -> Result { |
54a0048b | 1959 | f.write_char('"')?; |
b039eaaf SL |
1960 | let mut from = 0; |
1961 | for (i, c) in self.char_indices() { | |
5bcae85e | 1962 | let esc = c.escape_debug(); |
b039eaaf | 1963 | // If char needs escaping, flush backlog so far and write, else skip |
3157f602 | 1964 | if esc.len() != 1 { |
54a0048b | 1965 | f.write_str(&self[from..i])?; |
b039eaaf | 1966 | for c in esc { |
54a0048b | 1967 | f.write_char(c)?; |
b039eaaf SL |
1968 | } |
1969 | from = i + c.len_utf8(); | |
1970 | } | |
1a4d82fc | 1971 | } |
54a0048b | 1972 | f.write_str(&self[from..])?; |
b039eaaf | 1973 | f.write_char('"') |
1a4d82fc JJ |
1974 | } |
1975 | } | |
1976 | ||
85aaf69f SL |
1977 | #[stable(feature = "rust1", since = "1.0.0")] |
1978 | impl Display for str { | |
1a4d82fc JJ |
1979 | fn fmt(&self, f: &mut Formatter) -> Result { |
1980 | f.pad(self) | |
1981 | } | |
1982 | } | |
1983 | ||
85aaf69f SL |
1984 | #[stable(feature = "rust1", since = "1.0.0")] |
1985 | impl Debug for char { | |
1a4d82fc | 1986 | fn fmt(&self, f: &mut Formatter) -> Result { |
54a0048b | 1987 | f.write_char('\'')?; |
5bcae85e | 1988 | for c in self.escape_debug() { |
54a0048b | 1989 | f.write_char(c)? |
1a4d82fc | 1990 | } |
b039eaaf | 1991 | f.write_char('\'') |
1a4d82fc JJ |
1992 | } |
1993 | } | |
1994 | ||
85aaf69f SL |
1995 | #[stable(feature = "rust1", since = "1.0.0")] |
1996 | impl Display for char { | |
1a4d82fc | 1997 | fn fmt(&self, f: &mut Formatter) -> Result { |
62682a34 SL |
1998 | if f.width.is_none() && f.precision.is_none() { |
1999 | f.write_char(*self) | |
2000 | } else { | |
c30ab7b3 | 2001 | f.pad(self.encode_utf8(&mut [0; 4])) |
62682a34 | 2002 | } |
1a4d82fc JJ |
2003 | } |
2004 | } | |
2005 | ||
85aaf69f | 2006 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 2007 | impl<T: ?Sized> Pointer for *const T { |
1a4d82fc | 2008 | fn fmt(&self, f: &mut Formatter) -> Result { |
9346a6ac AL |
2009 | let old_width = f.width; |
2010 | let old_flags = f.flags; | |
2011 | ||
2012 | // The alternate flag is already treated by LowerHex as being special- | |
2013 | // it denotes whether to prefix with 0x. We use it to work out whether | |
2014 | // or not to zero extend, and then unconditionally set it to get the | |
2015 | // prefix. | |
b039eaaf | 2016 | if f.alternate() { |
9346a6ac AL |
2017 | f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); |
2018 | ||
2019 | if let None = f.width { | |
9cc50fc6 | 2020 | f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2); |
9346a6ac AL |
2021 | } |
2022 | } | |
c34b1796 | 2023 | f.flags |= 1 << (FlagV1::Alternate as u32); |
9346a6ac | 2024 | |
7453a54e | 2025 | let ret = LowerHex::fmt(&(*self as *const () as usize), f); |
9346a6ac AL |
2026 | |
2027 | f.width = old_width; | |
2028 | f.flags = old_flags; | |
2029 | ||
1a4d82fc JJ |
2030 | ret |
2031 | } | |
2032 | } | |
2033 | ||
85aaf69f | 2034 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 2035 | impl<T: ?Sized> Pointer for *mut T { |
1a4d82fc JJ |
2036 | fn fmt(&self, f: &mut Formatter) -> Result { |
2037 | Pointer::fmt(&(*self as *const T), f) | |
2038 | } | |
2039 | } | |
2040 | ||
85aaf69f | 2041 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 2042 | impl<'a, T: ?Sized> Pointer for &'a T { |
1a4d82fc JJ |
2043 | fn fmt(&self, f: &mut Formatter) -> Result { |
2044 | Pointer::fmt(&(*self as *const T), f) | |
2045 | } | |
2046 | } | |
2047 | ||
85aaf69f | 2048 | #[stable(feature = "rust1", since = "1.0.0")] |
7453a54e | 2049 | impl<'a, T: ?Sized> Pointer for &'a mut T { |
1a4d82fc JJ |
2050 | fn fmt(&self, f: &mut Formatter) -> Result { |
2051 | Pointer::fmt(&(&**self as *const T), f) | |
2052 | } | |
2053 | } | |
2054 | ||
85aaf69f | 2055 | // Implementation of Display/Debug for various core types |
1a4d82fc | 2056 | |
85aaf69f | 2057 | #[stable(feature = "rust1", since = "1.0.0")] |
c30ab7b3 | 2058 | impl<T: ?Sized> Debug for *const T { |
1a4d82fc JJ |
2059 | fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } |
2060 | } | |
85aaf69f | 2061 | #[stable(feature = "rust1", since = "1.0.0")] |
c30ab7b3 | 2062 | impl<T: ?Sized> Debug for *mut T { |
1a4d82fc JJ |
2063 | fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } |
2064 | } | |
2065 | ||
2066 | macro_rules! peel { | |
2067 | ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) | |
2068 | } | |
2069 | ||
2070 | macro_rules! tuple { | |
2071 | () => (); | |
2072 | ( $($name:ident,)+ ) => ( | |
85aaf69f | 2073 | #[stable(feature = "rust1", since = "1.0.0")] |
041b39d2 | 2074 | impl<$($name:Debug),*> Debug for ($($name,)*) where last_type!($($name,)+): ?Sized { |
9cc50fc6 | 2075 | #[allow(non_snake_case, unused_assignments, deprecated)] |
1a4d82fc | 2076 | fn fmt(&self, f: &mut Formatter) -> Result { |
c1a9b12d | 2077 | let mut builder = f.debug_tuple(""); |
1a4d82fc | 2078 | let ($(ref $name,)*) = *self; |
1a4d82fc | 2079 | $( |
041b39d2 | 2080 | builder.field(&$name); |
1a4d82fc | 2081 | )* |
c1a9b12d | 2082 | |
c1a9b12d | 2083 | builder.finish() |
1a4d82fc JJ |
2084 | } |
2085 | } | |
2086 | peel! { $($name,)* } | |
2087 | ) | |
2088 | } | |
2089 | ||
041b39d2 XL |
2090 | macro_rules! last_type { |
2091 | ($a:ident,) => { $a }; | |
2092 | ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; | |
2093 | } | |
2094 | ||
1a4d82fc JJ |
2095 | tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } |
2096 | ||
85aaf69f SL |
2097 | #[stable(feature = "rust1", since = "1.0.0")] |
2098 | impl<T: Debug> Debug for [T] { | |
1a4d82fc | 2099 | fn fmt(&self, f: &mut Formatter) -> Result { |
62682a34 | 2100 | f.debug_list().entries(self.iter()).finish() |
1a4d82fc JJ |
2101 | } |
2102 | } | |
2103 | ||
85aaf69f SL |
2104 | #[stable(feature = "rust1", since = "1.0.0")] |
2105 | impl Debug for () { | |
2c00a5a8 | 2106 | #[inline] |
1a4d82fc JJ |
2107 | fn fmt(&self, f: &mut Formatter) -> Result { |
2108 | f.pad("()") | |
2109 | } | |
2110 | } | |
92a42be0 | 2111 | #[stable(feature = "rust1", since = "1.0.0")] |
9cc50fc6 | 2112 | impl<T: ?Sized> Debug for PhantomData<T> { |
1a4d82fc | 2113 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 2114 | f.pad("PhantomData") |
1a4d82fc JJ |
2115 | } |
2116 | } | |
2117 | ||
85aaf69f SL |
2118 | #[stable(feature = "rust1", since = "1.0.0")] |
2119 | impl<T: Copy + Debug> Debug for Cell<T> { | |
1a4d82fc | 2120 | fn fmt(&self, f: &mut Formatter) -> Result { |
54a0048b SL |
2121 | f.debug_struct("Cell") |
2122 | .field("value", &self.get()) | |
2123 | .finish() | |
1a4d82fc JJ |
2124 | } |
2125 | } | |
2126 | ||
85aaf69f | 2127 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 2128 | impl<T: ?Sized + Debug> Debug for RefCell<T> { |
1a4d82fc | 2129 | fn fmt(&self, f: &mut Formatter) -> Result { |
476ff2be SL |
2130 | match self.try_borrow() { |
2131 | Ok(borrow) => { | |
54a0048b | 2132 | f.debug_struct("RefCell") |
476ff2be | 2133 | .field("value", &borrow) |
54a0048b SL |
2134 | .finish() |
2135 | } | |
476ff2be | 2136 | Err(_) => { |
ea8adc8c XL |
2137 | // The RefCell is mutably borrowed so we can't look at its value |
2138 | // here. Show a placeholder instead. | |
2139 | struct BorrowedPlaceholder; | |
2140 | ||
2141 | impl Debug for BorrowedPlaceholder { | |
2142 | fn fmt(&self, f: &mut Formatter) -> Result { | |
2143 | f.write_str("<borrowed>") | |
2144 | } | |
2145 | } | |
2146 | ||
54a0048b | 2147 | f.debug_struct("RefCell") |
ea8adc8c | 2148 | .field("value", &BorrowedPlaceholder) |
54a0048b | 2149 | .finish() |
85aaf69f | 2150 | } |
85aaf69f | 2151 | } |
1a4d82fc JJ |
2152 | } |
2153 | } | |
2154 | ||
85aaf69f | 2155 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 2156 | impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> { |
1a4d82fc | 2157 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 2158 | Debug::fmt(&**self, f) |
1a4d82fc JJ |
2159 | } |
2160 | } | |
2161 | ||
85aaf69f | 2162 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 2163 | impl<'b, T: ?Sized + Debug> Debug for RefMut<'b, T> { |
1a4d82fc | 2164 | fn fmt(&self, f: &mut Formatter) -> Result { |
85aaf69f | 2165 | Debug::fmt(&*(self.deref()), f) |
1a4d82fc JJ |
2166 | } |
2167 | } | |
2168 | ||
54a0048b SL |
2169 | #[stable(feature = "core_impl_debug", since = "1.9.0")] |
2170 | impl<T: ?Sized + Debug> Debug for UnsafeCell<T> { | |
2171 | fn fmt(&self, f: &mut Formatter) -> Result { | |
2172 | f.pad("UnsafeCell") | |
2173 | } | |
2174 | } | |
2175 | ||
1a4d82fc JJ |
2176 | // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, |
2177 | // it's a lot easier than creating all of the rt::Piece structures here. |