Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| //! Utilities for formatting and printing strings. | |
| #![stable(feature = "rust1", since = "1.0.0")] | |
| use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut}; | |
| use marker::PhantomData; | |
| use mem; | |
| use num::flt2dec; | |
| use ops::Deref; | |
| use result; | |
| use slice; | |
| use str; | |
| mod float; | |
| mod num; | |
| mod builders; | |
| #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
| /// Possible alignments returned by `Formatter::align` | |
| #[derive(Debug)] | |
| pub enum Alignment { | |
| #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
| /// Indication that contents should be left-aligned. | |
| Left, | |
| #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
| /// Indication that contents should be right-aligned. | |
| Right, | |
| #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
| /// Indication that contents should be center-aligned. | |
| Center, | |
| } | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| #[doc(hidden)] | |
| pub mod rt { | |
| pub mod v1; | |
| } | |
| /// The type returned by formatter methods. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// #[derive(Debug)] | |
| /// struct Triangle { | |
| /// a: f32, | |
| /// b: f32, | |
| /// c: f32 | |
| /// } | |
| /// | |
| /// impl fmt::Display for Triangle { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// write!(f, "({}, {}, {})", self.a, self.b, self.c) | |
| /// } | |
| /// } | |
| /// | |
| /// let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 }; | |
| /// | |
| /// println!("{}", pythagorean_triple); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub type Result = result::Result<(), Error>; | |
| /// The error type which is returned from formatting a message into a stream. | |
| /// | |
| /// This type does not support transmission of an error other than that an error | |
| /// occurred. Any extra information must be arranged to be transmitted through | |
| /// some other means. | |
| /// | |
| /// An important thing to remember is that the type `fmt::Error` should not be | |
| /// confused with [`std::io::Error`] or [`std::error::Error`], which you may also | |
| /// have in scope. | |
| /// | |
| /// [`std::io::Error`]: ../../std/io/struct.Error.html | |
| /// [`std::error::Error`]: ../../std/error/trait.Error.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt::{self, write}; | |
| /// | |
| /// let mut output = String::new(); | |
| /// if let Err(fmt::Error) = write(&mut output, format_args!("Hello {}!", "world")) { | |
| /// panic!("An error occurred"); | |
| /// } | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] | |
| pub struct Error; | |
| /// A collection of methods that are required to format a message into a stream. | |
| /// | |
| /// This trait is the type which this modules requires when formatting | |
| /// information. This is similar to the standard library's [`io::Write`] trait, | |
| /// but it is only intended for use in libcore. | |
| /// | |
| /// This trait should generally not be implemented by consumers of the standard | |
| /// library. The [`write!`] macro accepts an instance of [`io::Write`], and the | |
| /// [`io::Write`] trait is favored over implementing this trait. | |
| /// | |
| /// [`write!`]: ../../std/macro.write.html | |
| /// [`io::Write`]: ../../std/io/trait.Write.html | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait Write { | |
| /// Writes a slice of bytes into this writer, returning whether the write | |
| /// succeeded. | |
| /// | |
| /// This method can only succeed if the entire byte slice was successfully | |
| /// written, and this method will not return until all data has been | |
| /// written or an error occurs. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an instance of [`Error`] on error. | |
| /// | |
| /// [`Error`]: struct.Error.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt::{Error, Write}; | |
| /// | |
| /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> { | |
| /// f.write_str(s) | |
| /// } | |
| /// | |
| /// let mut buf = String::new(); | |
| /// writer(&mut buf, "hola").unwrap(); | |
| /// assert_eq!(&buf, "hola"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn write_str(&mut self, s: &str) -> Result; | |
| /// Writes a [`char`] into this writer, returning whether the write succeeded. | |
| /// | |
| /// A single [`char`] may be encoded as more than one byte. | |
| /// This method can only succeed if the entire byte sequence was successfully | |
| /// written, and this method will not return until all data has been | |
| /// written or an error occurs. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an instance of [`Error`] on error. | |
| /// | |
| /// [`char`]: ../../std/primitive.char.html | |
| /// [`Error`]: struct.Error.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt::{Error, Write}; | |
| /// | |
| /// fn writer<W: Write>(f: &mut W, c: char) -> Result<(), Error> { | |
| /// f.write_char(c) | |
| /// } | |
| /// | |
| /// let mut buf = String::new(); | |
| /// writer(&mut buf, 'a').unwrap(); | |
| /// writer(&mut buf, 'b').unwrap(); | |
| /// assert_eq!(&buf, "ab"); | |
| /// ``` | |
| #[stable(feature = "fmt_write_char", since = "1.1.0")] | |
| fn write_char(&mut self, c: char) -> Result { | |
| self.write_str(c.encode_utf8(&mut [0; 4])) | |
| } | |
| /// Glue for usage of the [`write!`] macro with implementors of this trait. | |
| /// | |
| /// This method should generally not be invoked manually, but rather through | |
| /// the [`write!`] macro itself. | |
| /// | |
| /// [`write!`]: ../../std/macro.write.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt::{Error, Write}; | |
| /// | |
| /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> { | |
| /// f.write_fmt(format_args!("{}", s)) | |
| /// } | |
| /// | |
| /// let mut buf = String::new(); | |
| /// writer(&mut buf, "world").unwrap(); | |
| /// assert_eq!(&buf, "world"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn write_fmt(mut self: &mut Self, args: Arguments) -> Result { | |
| write(&mut self, args) | |
| } | |
| } | |
| #[stable(feature = "fmt_write_blanket_impl", since = "1.4.0")] | |
| impl<W: Write + ?Sized> Write for &mut W { | |
| fn write_str(&mut self, s: &str) -> Result { | |
| (**self).write_str(s) | |
| } | |
| fn write_char(&mut self, c: char) -> Result { | |
| (**self).write_char(c) | |
| } | |
| fn write_fmt(&mut self, args: Arguments) -> Result { | |
| (**self).write_fmt(args) | |
| } | |
| } | |
| /// Configuration for formatting. | |
| /// | |
| /// A `Formatter` represents various options related to formatting. Users do not | |
| /// construct `Formatter`s directly; a mutable reference to one is passed to | |
| /// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`]. | |
| /// | |
| /// To interact with a `Formatter`, you'll call various methods to change the | |
| /// various options related to formatting. For examples, please see the | |
| /// documentation of the methods defined on `Formatter` below. | |
| /// | |
| /// [`Debug`]: trait.Debug.html | |
| /// [`Display`]: trait.Display.html | |
| #[allow(missing_debug_implementations)] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub struct Formatter<'a> { | |
| flags: u32, | |
| fill: char, | |
| align: rt::v1::Alignment, | |
| width: Option<usize>, | |
| precision: Option<usize>, | |
| buf: &'a mut (dyn Write+'a), | |
| curarg: slice::Iter<'a, ArgumentV1<'a>>, | |
| args: &'a [ArgumentV1<'a>], | |
| } | |
| // NB. Argument is essentially an optimized partially applied formatting function, | |
| // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`. | |
| struct Void { | |
| _priv: (), | |
| /// Erases all oibits, because `Void` erases the type of the object that | |
| /// will be used to produce formatted output. Since we do not know what | |
| /// oibits the real types have (and they can have any or none), we need to | |
| /// take the most conservative approach and forbid all oibits. | |
| /// | |
| /// It was added after #45197 showed that one could share a `!Sync` | |
| /// object across threads by passing it into `format_args!`. | |
| _oibit_remover: PhantomData<*mut dyn Fn()>, | |
| } | |
| /// This struct represents the generic "argument" which is taken by the Xprintf | |
| /// family of functions. It contains a function to format the given value. At | |
| /// compile time it is ensured that the function and the value have the correct | |
| /// types, and then this struct is used to canonicalize arguments to one type. | |
| #[derive(Copy, Clone)] | |
| #[allow(missing_debug_implementations)] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| #[doc(hidden)] | |
| pub struct ArgumentV1<'a> { | |
| value: &'a Void, | |
| formatter: fn(&Void, &mut Formatter) -> Result, | |
| } | |
| impl<'a> ArgumentV1<'a> { | |
| #[inline(never)] | |
| fn show_usize(x: &usize, f: &mut Formatter) -> Result { | |
| Display::fmt(x, f) | |
| } | |
| #[doc(hidden)] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| pub fn new<'b, T>(x: &'b T, | |
| f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { | |
| unsafe { | |
| ArgumentV1 { | |
| formatter: mem::transmute(f), | |
| value: mem::transmute(x) | |
| } | |
| } | |
| } | |
| #[doc(hidden)] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| pub fn from_usize(x: &usize) -> ArgumentV1 { | |
| ArgumentV1::new(x, ArgumentV1::show_usize) | |
| } | |
| fn as_usize(&self) -> Option<usize> { | |
| if self.formatter as usize == ArgumentV1::show_usize as usize { | |
| Some(unsafe { *(self.value as *const _ as *const usize) }) | |
| } else { | |
| None | |
| } | |
| } | |
| } | |
| // flags available in the v1 format of format_args | |
| #[derive(Copy, Clone)] | |
| enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex } | |
| impl<'a> Arguments<'a> { | |
| /// When using the format_args!() macro, this function is used to generate the | |
| /// Arguments structure. | |
| #[doc(hidden)] #[inline] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| pub fn new_v1(pieces: &'a [&'a str], | |
| args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { | |
| Arguments { | |
| pieces, | |
| fmt: None, | |
| args, | |
| } | |
| } | |
| /// This function is used to specify nonstandard formatting parameters. | |
| /// The `pieces` array must be at least as long as `fmt` to construct | |
| /// a valid Arguments structure. Also, any `Count` within `fmt` that is | |
| /// `CountIsParam` or `CountIsNextParam` has to point to an argument | |
| /// created with `argumentusize`. However, failing to do so doesn't cause | |
| /// unsafety, but will ignore invalid . | |
| #[doc(hidden)] #[inline] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| pub fn new_v1_formatted(pieces: &'a [&'a str], | |
| args: &'a [ArgumentV1<'a>], | |
| fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { | |
| Arguments { | |
| pieces, | |
| fmt: Some(fmt), | |
| args, | |
| } | |
| } | |
| /// Estimates the length of the formatted text. | |
| /// | |
| /// This is intended to be used for setting initial `String` capacity | |
| /// when using `format!`. Note: this is neither the lower nor upper bound. | |
| #[doc(hidden)] #[inline] | |
| #[unstable(feature = "fmt_internals", reason = "internal to format_args!", | |
| issue = "0")] | |
| pub fn estimated_capacity(&self) -> usize { | |
| let pieces_length: usize = self.pieces.iter() | |
| .map(|x| x.len()).sum(); | |
| if self.args.is_empty() { | |
| pieces_length | |
| } else if self.pieces[0] == "" && pieces_length < 16 { | |
| // If the format string starts with an argument, | |
| // don't preallocate anything, unless length | |
| // of pieces is significant. | |
| 0 | |
| } else { | |
| // There are some arguments, so any additional push | |
| // will reallocate the string. To avoid that, | |
| // we're "pre-doubling" the capacity here. | |
| pieces_length.checked_mul(2).unwrap_or(0) | |
| } | |
| } | |
| } | |
| /// This structure represents a safely precompiled version of a format string | |
| /// and its arguments. This cannot be generated at runtime because it cannot | |
| /// safely be done, so no constructors are given and the fields are private | |
| /// to prevent modification. | |
| /// | |
| /// The [`format_args!`] macro will safely create an instance of this structure. | |
| /// The macro validates the format string at compile-time so usage of the | |
| /// [`write`] and [`format`] functions can be safely performed. | |
| /// | |
| /// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` | |
| /// and `Display` contexts as seen below. The example also shows that `Debug` | |
| /// and `Display` format to the same thing: the interpolated format string | |
| /// in `format_args!`. | |
| /// | |
| /// ```rust | |
| /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); | |
| /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); | |
| /// assert_eq!("1 foo 2", display); | |
| /// assert_eq!(display, debug); | |
| /// ``` | |
| /// | |
| /// [`format_args!`]: ../../std/macro.format_args.html | |
| /// [`format`]: ../../std/fmt/fn.format.html | |
| /// [`write`]: ../../std/fmt/fn.write.html | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[derive(Copy, Clone)] | |
| pub struct Arguments<'a> { | |
| // Format string pieces to print. | |
| pieces: &'a [&'a str], | |
| // Placeholder specs, or `None` if all specs are default (as in "{}{}"). | |
| fmt: Option<&'a [rt::v1::Argument]>, | |
| // Dynamic arguments for interpolation, to be interleaved with string | |
| // pieces. (Every argument is preceded by a string piece.) | |
| args: &'a [ArgumentV1<'a>], | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Debug for Arguments<'_> { | |
| fn fmt(&self, fmt: &mut Formatter) -> Result { | |
| Display::fmt(self, fmt) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Display for Arguments<'_> { | |
| fn fmt(&self, fmt: &mut Formatter) -> Result { | |
| write(fmt.buf, *self) | |
| } | |
| } | |
| /// `?` formatting. | |
| /// | |
| /// `Debug` should format the output in a programmer-facing, debugging context. | |
| /// | |
| /// Generally speaking, you should just `derive` a `Debug` implementation. | |
| /// | |
| /// When used with the alternate format specifier `#?`, the output is pretty-printed. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// This trait can be used with `#[derive]` if all fields implement `Debug`. When | |
| /// `derive`d for structs, it will use the name of the `struct`, then `{`, then a | |
| /// comma-separated list of each field's name and `Debug` value, then `}`. For | |
| /// `enum`s, it will use the name of the variant and, if applicable, `(`, then the | |
| /// `Debug` values of the fields, then `)`. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Deriving an implementation: | |
| /// | |
| /// ``` | |
| /// #[derive(Debug)] | |
| /// struct Point { | |
| /// x: i32, | |
| /// y: i32, | |
| /// } | |
| /// | |
| /// let origin = Point { x: 0, y: 0 }; | |
| /// | |
| /// println!("The origin is: {:?}", origin); | |
| /// ``` | |
| /// | |
| /// Manually implementing: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Point { | |
| /// x: i32, | |
| /// y: i32, | |
| /// } | |
| /// | |
| /// impl fmt::Debug for Point { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) | |
| /// } | |
| /// } | |
| /// | |
| /// let origin = Point { x: 0, y: 0 }; | |
| /// | |
| /// println!("The origin is: {:?}", origin); | |
| /// ``` | |
| /// | |
| /// This outputs: | |
| /// | |
| /// ```text | |
| /// The origin is: Point { x: 0, y: 0 } | |
| /// ``` | |
| /// | |
| /// There are a number of `debug_*` methods on [`Formatter`] to help you with manual | |
| /// implementations, such as [`debug_struct`][debug_struct]. | |
| /// | |
| /// `Debug` implementations using either `derive` or the debug builder API | |
| /// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`. | |
| /// | |
| /// [debug_struct]: ../../std/fmt/struct.Formatter.html#method.debug_struct | |
| /// [`Formatter`]: ../../std/fmt/struct.Formatter.html | |
| /// | |
| /// Pretty-printing with `#?`: | |
| /// | |
| /// ``` | |
| /// #[derive(Debug)] | |
| /// struct Point { | |
| /// x: i32, | |
| /// y: i32, | |
| /// } | |
| /// | |
| /// let origin = Point { x: 0, y: 0 }; | |
| /// | |
| /// println!("The origin is: {:#?}", origin); | |
| /// ``` | |
| /// | |
| /// This outputs: | |
| /// | |
| /// ```text | |
| /// The origin is: Point { | |
| /// x: 0, | |
| /// y: 0 | |
| /// } | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[rustc_on_unimplemented( | |
| on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`", | |
| note="add `#[derive(Debug)]` or manually implement `{Debug}`"), | |
| message="`{Self}` doesn't implement `{Debug}`", | |
| label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", | |
| )] | |
| #[doc(alias = "{:?}")] | |
| #[lang = "debug_trait"] | |
| pub trait Debug { | |
| /// Formats the value using the given formatter. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Position { | |
| /// longitude: f32, | |
| /// latitude: f32, | |
| /// } | |
| /// | |
| /// impl fmt::Debug for Position { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// write!(f, "({:?}, {:?})", self.longitude, self.latitude) | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!("(1.987, 2.983)".to_owned(), | |
| /// format!("{:?}", Position { longitude: 1.987, latitude: 2.983, })); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// Format trait for an empty format, `{}`. | |
| /// | |
| /// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing | |
| /// output, and so cannot be derived. | |
| /// | |
| /// [debug]: trait.Debug.html | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Implementing `Display` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Point { | |
| /// x: i32, | |
| /// y: i32, | |
| /// } | |
| /// | |
| /// impl fmt::Display for Point { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// write!(f, "({}, {})", self.x, self.y) | |
| /// } | |
| /// } | |
| /// | |
| /// let origin = Point { x: 0, y: 0 }; | |
| /// | |
| /// println!("The origin is: {}", origin); | |
| /// ``` | |
| #[rustc_on_unimplemented( | |
| on( | |
| _Self="std::path::Path", | |
| label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it", | |
| note="call `.display()` or `.to_string_lossy()` to safely print paths, \ | |
| as they may contain non-Unicode data" | |
| ), | |
| message="`{Self}` doesn't implement `{Display}`", | |
| label="`{Self}` cannot be formatted with the default formatter", | |
| note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead", | |
| )] | |
| #[doc(alias = "{}")] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait Display { | |
| /// Formats the value using the given formatter. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Position { | |
| /// longitude: f32, | |
| /// latitude: f32, | |
| /// } | |
| /// | |
| /// impl fmt::Display for Position { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// write!(f, "({}, {})", self.longitude, self.latitude) | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!("(1.987, 2.983)".to_owned(), | |
| /// format!("{}", Position { longitude: 1.987, latitude: 2.983, })); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `o` formatting. | |
| /// | |
| /// The `Octal` trait should format its output as a number in base-8. | |
| /// | |
| /// For primitive signed integers (`i8` to `i128`, and `isize`), | |
| /// negative values are formatted as the two’s complement representation. | |
| /// | |
| /// The alternate flag, `#`, adds a `0o` in front of the output. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `i32`: | |
| /// | |
| /// ``` | |
| /// let x = 42; // 42 is '52' in octal | |
| /// | |
| /// assert_eq!(format!("{:o}", x), "52"); | |
| /// assert_eq!(format!("{:#o}", x), "0o52"); | |
| /// | |
| /// assert_eq!(format!("{:o}", -16), "37777777760"); | |
| /// ``` | |
| /// | |
| /// Implementing `Octal` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::Octal for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// | |
| /// write!(f, "{:o}", val) // delegate to i32's implementation | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(9); | |
| /// | |
| /// println!("l as octal is: {:o}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait Octal { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `b` formatting. | |
| /// | |
| /// The `Binary` trait should format its output as a number in binary. | |
| /// | |
| /// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]), | |
| /// negative values are formatted as the two’s complement representation. | |
| /// | |
| /// The alternate flag, `#`, adds a `0b` in front of the output. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with [`i32`]: | |
| /// | |
| /// ``` | |
| /// let x = 42; // 42 is '101010' in binary | |
| /// | |
| /// assert_eq!(format!("{:b}", x), "101010"); | |
| /// assert_eq!(format!("{:#b}", x), "0b101010"); | |
| /// | |
| /// assert_eq!(format!("{:b}", -16), "11111111111111111111111111110000"); | |
| /// ``` | |
| /// | |
| /// Implementing `Binary` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::Binary for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// | |
| /// write!(f, "{:b}", val) // delegate to i32's implementation | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(107); | |
| /// | |
| /// println!("l as binary is: {:b}", l); | |
| /// ``` | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// [`i8`]: ../../std/primitive.i8.html | |
| /// [`i128`]: ../../std/primitive.i128.html | |
| /// [`isize`]: ../../std/primitive.isize.html | |
| /// [`i32`]: ../../std/primitive.i32.html | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait Binary { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `x` formatting. | |
| /// | |
| /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` | |
| /// in lower case. | |
| /// | |
| /// For primitive signed integers (`i8` to `i128`, and `isize`), | |
| /// negative values are formatted as the two’s complement representation. | |
| /// | |
| /// The alternate flag, `#`, adds a `0x` in front of the output. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `i32`: | |
| /// | |
| /// ``` | |
| /// let x = 42; // 42 is '2a' in hex | |
| /// | |
| /// assert_eq!(format!("{:x}", x), "2a"); | |
| /// assert_eq!(format!("{:#x}", x), "0x2a"); | |
| /// | |
| /// assert_eq!(format!("{:x}", -16), "fffffff0"); | |
| /// ``` | |
| /// | |
| /// Implementing `LowerHex` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::LowerHex for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// | |
| /// write!(f, "{:x}", val) // delegate to i32's implementation | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(9); | |
| /// | |
| /// println!("l as hex is: {:x}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait LowerHex { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `X` formatting. | |
| /// | |
| /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` | |
| /// in upper case. | |
| /// | |
| /// For primitive signed integers (`i8` to `i128`, and `isize`), | |
| /// negative values are formatted as the two’s complement representation. | |
| /// | |
| /// The alternate flag, `#`, adds a `0x` in front of the output. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `i32`: | |
| /// | |
| /// ``` | |
| /// let x = 42; // 42 is '2A' in hex | |
| /// | |
| /// assert_eq!(format!("{:X}", x), "2A"); | |
| /// assert_eq!(format!("{:#X}", x), "0x2A"); | |
| /// | |
| /// assert_eq!(format!("{:X}", -16), "FFFFFFF0"); | |
| /// ``` | |
| /// | |
| /// Implementing `UpperHex` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::UpperHex for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// | |
| /// write!(f, "{:X}", val) // delegate to i32's implementation | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(9); | |
| /// | |
| /// println!("l as hex is: {:X}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait UpperHex { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `p` formatting. | |
| /// | |
| /// The `Pointer` trait should format its output as a memory location. This is commonly presented | |
| /// as hexadecimal. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `&i32`: | |
| /// | |
| /// ``` | |
| /// let x = &42; | |
| /// | |
| /// let address = format!("{:p}", x); // this produces something like '0x7f06092ac6d0' | |
| /// ``` | |
| /// | |
| /// Implementing `Pointer` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::Pointer for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// // use `as` to convert to a `*const T`, which implements Pointer, which we can use | |
| /// | |
| /// write!(f, "{:p}", self as *const Length) | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(42); | |
| /// | |
| /// println!("l is in memory here: {:p}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait Pointer { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `e` formatting. | |
| /// | |
| /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `i32`: | |
| /// | |
| /// ``` | |
| /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation | |
| /// | |
| /// assert_eq!(format!("{:e}", x), "4.2e1"); | |
| /// ``` | |
| /// | |
| /// Implementing `LowerExp` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::LowerExp for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// write!(f, "{}e1", val / 10) | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(100); | |
| /// | |
| /// println!("l in scientific notation is: {:e}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait LowerExp { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// `E` formatting. | |
| /// | |
| /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. | |
| /// | |
| /// For more information on formatters, see [the module-level documentation][module]. | |
| /// | |
| /// [module]: ../../std/fmt/index.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage with `f32`: | |
| /// | |
| /// ``` | |
| /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation | |
| /// | |
| /// assert_eq!(format!("{:E}", x), "4.2E1"); | |
| /// ``` | |
| /// | |
| /// Implementing `UpperExp` on a type: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Length(i32); | |
| /// | |
| /// impl fmt::UpperExp for Length { | |
| /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| /// let val = self.0; | |
| /// write!(f, "{}E1", val / 10) | |
| /// } | |
| /// } | |
| /// | |
| /// let l = Length(100); | |
| /// | |
| /// println!("l in scientific notation is: {:E}", l); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub trait UpperExp { | |
| /// Formats the value using the given formatter. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| fn fmt(&self, f: &mut Formatter) -> Result; | |
| } | |
| /// The `write` function takes an output stream, and an `Arguments` struct | |
| /// that can be precompiled with the `format_args!` macro. | |
| /// | |
| /// The arguments will be formatted according to the specified format string | |
| /// into the output stream provided. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// let mut output = String::new(); | |
| /// fmt::write(&mut output, format_args!("Hello {}!", "world")) | |
| /// .expect("Error occurred while trying to write in String"); | |
| /// assert_eq!(output, "Hello world!"); | |
| /// ``` | |
| /// | |
| /// Please note that using [`write!`] might be preferable. Example: | |
| /// | |
| /// ``` | |
| /// use std::fmt::Write; | |
| /// | |
| /// let mut output = String::new(); | |
| /// write!(&mut output, "Hello {}!", "world") | |
| /// .expect("Error occurred while trying to write in String"); | |
| /// assert_eq!(output, "Hello world!"); | |
| /// ``` | |
| /// | |
| /// [`write!`]: ../../std/macro.write.html | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn write(output: &mut dyn Write, args: Arguments) -> Result { | |
| let mut formatter = Formatter { | |
| flags: 0, | |
| width: None, | |
| precision: None, | |
| buf: output, | |
| align: rt::v1::Alignment::Unknown, | |
| fill: ' ', | |
| args: args.args, | |
| curarg: args.args.iter(), | |
| }; | |
| let mut idx = 0; | |
| match args.fmt { | |
| None => { | |
| // We can use default formatting parameters for all arguments. | |
| for (arg, piece) in args.args.iter().zip(args.pieces.iter()) { | |
| formatter.buf.write_str(*piece)?; | |
| (arg.formatter)(arg.value, &mut formatter)?; | |
| idx += 1; | |
| } | |
| } | |
| Some(fmt) => { | |
| // Every spec has a corresponding argument that is preceded by | |
| // a string piece. | |
| for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { | |
| formatter.buf.write_str(*piece)?; | |
| formatter.run(arg)?; | |
| idx += 1; | |
| } | |
| } | |
| } | |
| // There can be only one trailing string piece left. | |
| if let Some(piece) = args.pieces.get(idx) { | |
| formatter.buf.write_str(*piece)?; | |
| } | |
| Ok(()) | |
| } | |
| /// Padding after the end of something. Returned by `Formatter::padding`. | |
| #[must_use = "don't forget to write the post padding"] | |
| struct PostPadding { | |
| fill: char, | |
| padding: usize, | |
| } | |
| impl PostPadding { | |
| fn new(fill: char, padding: usize) -> PostPadding { | |
| PostPadding { fill, padding } | |
| } | |
| /// Write this post padding. | |
| fn write(self, buf: &mut dyn Write) -> Result { | |
| for _ in 0..self.padding { | |
| buf.write_char(self.fill)?; | |
| } | |
| Ok(()) | |
| } | |
| } | |
| impl<'a> Formatter<'a> { | |
| fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> | |
| where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c) | |
| { | |
| Formatter { | |
| // We want to change this | |
| buf: wrap(self.buf), | |
| // And preserve these | |
| flags: self.flags, | |
| fill: self.fill, | |
| align: self.align, | |
| width: self.width, | |
| precision: self.precision, | |
| // These only exist in the struct for the `run` method, | |
| // which won’t be used together with this method. | |
| curarg: self.curarg.clone(), | |
| args: self.args, | |
| } | |
| } | |
| // First up is the collection of functions used to execute a format string | |
| // at runtime. This consumes all of the compile-time statics generated by | |
| // the format! syntax extension. | |
| fn run(&mut self, arg: &rt::v1::Argument) -> Result { | |
| // Fill in the format parameters into the formatter | |
| self.fill = arg.format.fill; | |
| self.align = arg.format.align; | |
| self.flags = arg.format.flags; | |
| self.width = self.getcount(&arg.format.width); | |
| self.precision = self.getcount(&arg.format.precision); | |
| // Extract the correct argument | |
| let value = match arg.position { | |
| rt::v1::Position::Next => { *self.curarg.next().unwrap() } | |
| rt::v1::Position::At(i) => self.args[i], | |
| }; | |
| // Then actually do some printing | |
| (value.formatter)(value.value, self) | |
| } | |
| fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> { | |
| match *cnt { | |
| rt::v1::Count::Is(n) => Some(n), | |
| rt::v1::Count::Implied => None, | |
| rt::v1::Count::Param(i) => { | |
| self.args[i].as_usize() | |
| } | |
| rt::v1::Count::NextParam => { | |
| self.curarg.next()?.as_usize() | |
| } | |
| } | |
| } | |
| // Helper methods used for padding and processing formatting arguments that | |
| // all formatting traits can use. | |
| /// Performs the correct padding for an integer which has already been | |
| /// emitted into a str. The str should *not* contain the sign for the | |
| /// integer, that will be added by this method. | |
| /// | |
| /// # Arguments | |
| /// | |
| /// * is_nonnegative - whether the original integer was either positive or zero. | |
| /// * prefix - if the '#' character (Alternate) is provided, this | |
| /// is the prefix to put in front of the number. | |
| /// * buf - the byte array that the number has been formatted into | |
| /// | |
| /// This function will correctly account for the flags provided as well as | |
| /// the minimum width. It will not take precision into account. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo { nb: i32 }; | |
| /// | |
| /// impl Foo { | |
| /// fn new(nb: i32) -> Foo { | |
| /// Foo { | |
| /// nb, | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// // We need to remove "-" from the number output. | |
| /// let tmp = self.nb.abs().to_string(); | |
| /// | |
| /// formatter.pad_integral(self.nb > 0, "Foo ", &tmp) | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{}", Foo::new(2)), "2"); | |
| /// assert_eq!(&format!("{}", Foo::new(-1)), "-1"); | |
| /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1"); | |
| /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn pad_integral(&mut self, | |
| is_nonnegative: bool, | |
| prefix: &str, | |
| buf: &str) | |
| -> Result { | |
| let mut width = buf.len(); | |
| let mut sign = None; | |
| if !is_nonnegative { | |
| sign = Some('-'); width += 1; | |
| } else if self.sign_plus() { | |
| sign = Some('+'); width += 1; | |
| } | |
| let prefix = if self.alternate() { | |
| width += prefix.chars().count(); | |
| Some(prefix) | |
| } else { | |
| None | |
| }; | |
| // Writes the sign if it exists, and then the prefix if it was requested | |
| #[inline(never)] | |
| fn write_prefix(f: &mut Formatter, sign: Option<char>, prefix: Option<&str>) -> Result { | |
| if let Some(c) = sign { | |
| f.buf.write_char(c)?; | |
| } | |
| if let Some(prefix) = prefix { | |
| f.buf.write_str(prefix) | |
| } else { | |
| Ok(()) | |
| } | |
| } | |
| // The `width` field is more of a `min-width` parameter at this point. | |
| match self.width { | |
| // If there's no minimum length requirements then we can just | |
| // write the bytes. | |
| None => { | |
| write_prefix(self, sign, prefix)?; | |
| self.buf.write_str(buf) | |
| } | |
| // Check if we're over the minimum width, if so then we can also | |
| // just write the bytes. | |
| Some(min) if width >= min => { | |
| write_prefix(self, sign, prefix)?; | |
| self.buf.write_str(buf) | |
| } | |
| // The sign and prefix goes before the padding if the fill character | |
| // is zero | |
| Some(min) if self.sign_aware_zero_pad() => { | |
| self.fill = '0'; | |
| self.align = rt::v1::Alignment::Right; | |
| write_prefix(self, sign, prefix)?; | |
| let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; | |
| self.buf.write_str(buf)?; | |
| post_padding.write(self.buf) | |
| } | |
| // Otherwise, the sign and prefix goes after the padding | |
| Some(min) => { | |
| let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; | |
| write_prefix(self, sign, prefix)?; | |
| self.buf.write_str(buf)?; | |
| post_padding.write(self.buf) | |
| } | |
| } | |
| } | |
| /// This function takes a string slice and emits it to the internal buffer | |
| /// after applying the relevant formatting flags specified. The flags | |
| /// recognized for generic strings are: | |
| /// | |
| /// * width - the minimum width of what to emit | |
| /// * fill/align - what to emit and where to emit it if the string | |
| /// provided needs to be padded | |
| /// * precision - the maximum length to emit, the string is truncated if it | |
| /// is longer than this length | |
| /// | |
| /// Notably this function ignores the `flag` parameters. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo; | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// formatter.pad("Foo") | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:<4}", Foo), "Foo "); | |
| /// assert_eq!(&format!("{:0>4}", Foo), "0Foo"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn pad(&mut self, s: &str) -> Result { | |
| // Make sure there's a fast path up front | |
| if self.width.is_none() && self.precision.is_none() { | |
| return self.buf.write_str(s); | |
| } | |
| // The `precision` field can be interpreted as a `max-width` for the | |
| // string being formatted. | |
| let s = if let Some(max) = self.precision { | |
| // If our string is longer that the precision, then we must have | |
| // truncation. However other flags like `fill`, `width` and `align` | |
| // must act as always. | |
| if let Some((i, _)) = s.char_indices().nth(max) { | |
| // LLVM here can't prove that `..i` won't panic `&s[..i]`, but | |
| // we know that it can't panic. Use `get` + `unwrap_or` to avoid | |
| // `unsafe` and otherwise don't emit any panic-related code | |
| // here. | |
| s.get(..i).unwrap_or(&s) | |
| } else { | |
| &s | |
| } | |
| } else { | |
| &s | |
| }; | |
| // The `width` field is more of a `min-width` parameter at this point. | |
| match self.width { | |
| // If we're under the maximum length, and there's no minimum length | |
| // requirements, then we can just emit the string | |
| None => self.buf.write_str(s), | |
| // If we're under the maximum width, check if we're over the minimum | |
| // width, if so it's as easy as just emitting the string. | |
| Some(width) if s.chars().count() >= width => { | |
| self.buf.write_str(s) | |
| } | |
| // If we're under both the maximum and the minimum width, then fill | |
| // up the minimum width with the specified string + some alignment. | |
| Some(width) => { | |
| let align = rt::v1::Alignment::Left; | |
| let post_padding = self.padding(width - s.chars().count(), align)?; | |
| self.buf.write_str(s)?; | |
| post_padding.write(self.buf) | |
| } | |
| } | |
| } | |
| /// Write the pre-padding and return the unwritten post-padding. Callers are | |
| /// responsible for ensuring post-padding is written after the thing that is | |
| /// being padded. | |
| fn padding( | |
| &mut self, | |
| padding: usize, | |
| default: rt::v1::Alignment | |
| ) -> result::Result<PostPadding, Error> { | |
| let align = match self.align { | |
| rt::v1::Alignment::Unknown => default, | |
| _ => self.align | |
| }; | |
| let (pre_pad, post_pad) = match align { | |
| rt::v1::Alignment::Left => (0, padding), | |
| rt::v1::Alignment::Right | | |
| rt::v1::Alignment::Unknown => (padding, 0), | |
| rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), | |
| }; | |
| for _ in 0..pre_pad { | |
| self.buf.write_char(self.fill)?; | |
| } | |
| Ok(PostPadding::new(self.fill, post_pad)) | |
| } | |
| /// Takes the formatted parts and applies the padding. | |
| /// Assumes that the caller already has rendered the parts with required precision, | |
| /// so that `self.precision` can be ignored. | |
| fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
| if let Some(mut width) = self.width { | |
| // for the sign-aware zero padding, we render the sign first and | |
| // behave as if we had no sign from the beginning. | |
| let mut formatted = formatted.clone(); | |
| let old_fill = self.fill; | |
| let old_align = self.align; | |
| let mut align = old_align; | |
| if self.sign_aware_zero_pad() { | |
| // a sign always goes first | |
| let sign = unsafe { str::from_utf8_unchecked(formatted.sign) }; | |
| self.buf.write_str(sign)?; | |
| // remove the sign from the formatted parts | |
| formatted.sign = b""; | |
| width = width.saturating_sub(sign.len()); | |
| align = rt::v1::Alignment::Right; | |
| self.fill = '0'; | |
| self.align = rt::v1::Alignment::Right; | |
| } | |
| // remaining parts go through the ordinary padding process. | |
| let len = formatted.len(); | |
| let ret = if width <= len { // no padding | |
| self.write_formatted_parts(&formatted) | |
| } else { | |
| let post_padding = self.padding(width - len, align)?; | |
| self.write_formatted_parts(&formatted)?; | |
| post_padding.write(self.buf) | |
| }; | |
| self.fill = old_fill; | |
| self.align = old_align; | |
| ret | |
| } else { | |
| // this is the common case and we take a shortcut | |
| self.write_formatted_parts(formatted) | |
| } | |
| } | |
| fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { | |
| fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { | |
| buf.write_str(unsafe { str::from_utf8_unchecked(s) }) | |
| } | |
| if !formatted.sign.is_empty() { | |
| write_bytes(self.buf, formatted.sign)?; | |
| } | |
| for part in formatted.parts { | |
| match *part { | |
| flt2dec::Part::Zero(mut nzeroes) => { | |
| const ZEROES: &str = // 64 zeroes | |
| "0000000000000000000000000000000000000000000000000000000000000000"; | |
| while nzeroes > ZEROES.len() { | |
| self.buf.write_str(ZEROES)?; | |
| nzeroes -= ZEROES.len(); | |
| } | |
| if nzeroes > 0 { | |
| self.buf.write_str(&ZEROES[..nzeroes])?; | |
| } | |
| } | |
| flt2dec::Part::Num(mut v) => { | |
| let mut s = [0; 5]; | |
| let len = part.len(); | |
| for c in s[..len].iter_mut().rev() { | |
| *c = b'0' + (v % 10) as u8; | |
| v /= 10; | |
| } | |
| write_bytes(self.buf, &s[..len])?; | |
| } | |
| flt2dec::Part::Copy(buf) => { | |
| write_bytes(self.buf, buf)?; | |
| } | |
| } | |
| } | |
| Ok(()) | |
| } | |
| /// Writes some data to the underlying buffer contained within this | |
| /// formatter. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo; | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// formatter.write_str("Foo") | |
| /// // This is equivalent to: | |
| /// // write!(formatter, "Foo") | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{}", Foo), "Foo"); | |
| /// assert_eq!(&format!("{:0>8}", Foo), "Foo"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn write_str(&mut self, data: &str) -> Result { | |
| self.buf.write_str(data) | |
| } | |
| /// Writes some formatted information into this instance. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// formatter.write_fmt(format_args!("Foo {}", self.0)) | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1"); | |
| /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2"); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn write_fmt(&mut self, fmt: Arguments) -> Result { | |
| write(self.buf, fmt) | |
| } | |
| /// Flags for formatting | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[rustc_deprecated(since = "1.24.0", | |
| reason = "use the `sign_plus`, `sign_minus`, `alternate`, \ | |
| or `sign_aware_zero_pad` methods instead")] | |
| pub fn flags(&self) -> u32 { self.flags } | |
| /// Character used as 'fill' whenever there is alignment. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo; | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// let c = formatter.fill(); | |
| /// if let Some(width) = formatter.width() { | |
| /// for _ in 0..width { | |
| /// write!(formatter, "{}", c)?; | |
| /// } | |
| /// Ok(()) | |
| /// } else { | |
| /// write!(formatter, "{}", c) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// // We set alignment to the left with ">". | |
| /// assert_eq!(&format!("{:G>3}", Foo), "GGG"); | |
| /// assert_eq!(&format!("{:t>6}", Foo), "tttttt"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn fill(&self) -> char { self.fill } | |
| /// Flag indicating what form of alignment was requested. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// extern crate core; | |
| /// | |
| /// use std::fmt::{self, Alignment}; | |
| /// | |
| /// struct Foo; | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// let s = if let Some(s) = formatter.align() { | |
| /// match s { | |
| /// Alignment::Left => "left", | |
| /// Alignment::Right => "right", | |
| /// Alignment::Center => "center", | |
| /// } | |
| /// } else { | |
| /// "into the void" | |
| /// }; | |
| /// write!(formatter, "{}", s) | |
| /// } | |
| /// } | |
| /// | |
| /// fn main() { | |
| /// assert_eq!(&format!("{:<}", Foo), "left"); | |
| /// assert_eq!(&format!("{:>}", Foo), "right"); | |
| /// assert_eq!(&format!("{:^}", Foo), "center"); | |
| /// assert_eq!(&format!("{}", Foo), "into the void"); | |
| /// } | |
| /// ``` | |
| #[stable(feature = "fmt_flags_align", since = "1.28.0")] | |
| pub fn align(&self) -> Option<Alignment> { | |
| match self.align { | |
| rt::v1::Alignment::Left => Some(Alignment::Left), | |
| rt::v1::Alignment::Right => Some(Alignment::Right), | |
| rt::v1::Alignment::Center => Some(Alignment::Center), | |
| rt::v1::Alignment::Unknown => None, | |
| } | |
| } | |
| /// Optionally specified integer width that the output should be. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// if let Some(width) = formatter.width() { | |
| /// // If we received a width, we use it | |
| /// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width) | |
| /// } else { | |
| /// // Otherwise we do nothing special | |
| /// write!(formatter, "Foo({})", self.0) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) "); | |
| /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn width(&self) -> Option<usize> { self.width } | |
| /// Optionally specified precision for numeric types. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(f32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// if let Some(precision) = formatter.precision() { | |
| /// // If we received a precision, we use it. | |
| /// write!(formatter, "Foo({1:.*})", precision, self.0) | |
| /// } else { | |
| /// // Otherwise we default to 2. | |
| /// write!(formatter, "Foo({:.2})", self.0) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); | |
| /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn precision(&self) -> Option<usize> { self.precision } | |
| /// Determines if the `+` flag was specified. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// if formatter.sign_plus() { | |
| /// write!(formatter, | |
| /// "Foo({}{})", | |
| /// if self.0 < 0 { '-' } else { '+' }, | |
| /// self.0) | |
| /// } else { | |
| /// write!(formatter, "Foo({})", self.0) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)"); | |
| /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 } | |
| /// Determines if the `-` flag was specified. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// if formatter.sign_minus() { | |
| /// // You want a minus sign? Have one! | |
| /// write!(formatter, "-Foo({})", self.0) | |
| /// } else { | |
| /// write!(formatter, "Foo({})", self.0) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)"); | |
| /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 } | |
| /// Determines if the `#` flag was specified. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// if formatter.alternate() { | |
| /// write!(formatter, "Foo({})", self.0) | |
| /// } else { | |
| /// write!(formatter, "{}", self.0) | |
| /// } | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)"); | |
| /// assert_eq!(&format!("{}", Foo(23)), "23"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 } | |
| /// Determines if the `0` flag was specified. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(i32); | |
| /// | |
| /// impl fmt::Display for Foo { | |
| /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| /// assert!(formatter.sign_aware_zero_pad()); | |
| /// assert_eq!(formatter.width(), Some(4)); | |
| /// // We ignore the formatter's options. | |
| /// write!(formatter, "{}", self.0) | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!(&format!("{:04}", Foo(23)), "23"); | |
| /// ``` | |
| #[stable(feature = "fmt_flags", since = "1.5.0")] | |
| pub fn sign_aware_zero_pad(&self) -> bool { | |
| self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 | |
| } | |
| // FIXME: Decide what public API we want for these two flags. | |
| // https://github.com/rust-lang/rust/issues/48584 | |
| fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 } | |
| fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 } | |
| /// Creates a [`DebugStruct`] builder designed to assist with creation of | |
| /// [`fmt::Debug`] implementations for structs. | |
| /// | |
| /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html | |
| /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// use std::net::Ipv4Addr; | |
| /// | |
| /// struct Foo { | |
| /// bar: i32, | |
| /// baz: String, | |
| /// addr: Ipv4Addr, | |
| /// } | |
| /// | |
| /// impl fmt::Debug for Foo { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_struct("Foo") | |
| /// .field("bar", &self.bar) | |
| /// .field("baz", &self.baz) | |
| /// .field("addr", &format_args!("{}", self.addr)) | |
| /// .finish() | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!( | |
| /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", | |
| /// format!("{:?}", Foo { | |
| /// bar: 10, | |
| /// baz: "Hello World".to_string(), | |
| /// addr: Ipv4Addr::new(127, 0, 0, 1), | |
| /// }) | |
| /// ); | |
| /// ``` | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { | |
| builders::debug_struct_new(self, name) | |
| } | |
| /// Creates a `DebugTuple` builder designed to assist with creation of | |
| /// `fmt::Debug` implementations for tuple structs. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// use std::marker::PhantomData; | |
| /// | |
| /// struct Foo<T>(i32, String, PhantomData<T>); | |
| /// | |
| /// impl<T> fmt::Debug for Foo<T> { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_tuple("Foo") | |
| /// .field(&self.0) | |
| /// .field(&self.1) | |
| /// .field(&format_args!("_")) | |
| /// .finish() | |
| /// } | |
| /// } | |
| /// | |
| /// assert_eq!( | |
| /// "Foo(10, \"Hello\", _)", | |
| /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::<u8>)) | |
| /// ); | |
| /// ``` | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { | |
| builders::debug_tuple_new(self, name) | |
| } | |
| /// Creates a `DebugList` builder designed to assist with creation of | |
| /// `fmt::Debug` implementations for list-like structures. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(Vec<i32>); | |
| /// | |
| /// impl fmt::Debug for Foo { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_list().entries(self.0.iter()).finish() | |
| /// } | |
| /// } | |
| /// | |
| /// // prints "[10, 11]" | |
| /// println!("{:?}", Foo(vec![10, 11])); | |
| /// ``` | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { | |
| builders::debug_list_new(self) | |
| } | |
| /// Creates a `DebugSet` builder designed to assist with creation of | |
| /// `fmt::Debug` implementations for set-like structures. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(Vec<i32>); | |
| /// | |
| /// impl fmt::Debug for Foo { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_set().entries(self.0.iter()).finish() | |
| /// } | |
| /// } | |
| /// | |
| /// // prints "{10, 11}" | |
| /// println!("{:?}", Foo(vec![10, 11])); | |
| /// ``` | |
| /// | |
| /// [`format_args!`]: ../../std/macro.format_args.html | |
| /// | |
| /// In this more complex example, we use [`format_args!`] and `.debug_set()` | |
| /// to build a list of match arms: | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// | |
| /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); | |
| /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); | |
| /// | |
| /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> | |
| /// where | |
| /// L: 'a + fmt::Debug, R: 'a + fmt::Debug | |
| /// { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// L::fmt(&(self.0).0, fmt)?; | |
| /// fmt.write_str(" => ")?; | |
| /// R::fmt(&(self.0).1, fmt) | |
| /// } | |
| /// } | |
| /// | |
| /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> | |
| /// where | |
| /// K: 'a + fmt::Debug, V: 'a + fmt::Debug | |
| /// { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_set() | |
| /// .entries(self.0.iter().map(Arm)) | |
| /// .entry(&Arm(&(format_args!("_"), &self.1))) | |
| /// .finish() | |
| /// } | |
| /// } | |
| /// ``` | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { | |
| builders::debug_set_new(self) | |
| } | |
| /// Creates a `DebugMap` builder designed to assist with creation of | |
| /// `fmt::Debug` implementations for map-like structures. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ```rust | |
| /// use std::fmt; | |
| /// | |
| /// struct Foo(Vec<(String, i32)>); | |
| /// | |
| /// impl fmt::Debug for Foo { | |
| /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
| /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() | |
| /// } | |
| /// } | |
| /// | |
| /// // prints "{"A": 10, "B": 11}" | |
| /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); | |
| /// ``` | |
| #[stable(feature = "debug_builders", since = "1.2.0")] | |
| pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { | |
| builders::debug_map_new(self) | |
| } | |
| } | |
| #[stable(since = "1.2.0", feature = "formatter_write")] | |
| impl Write for Formatter<'_> { | |
| fn write_str(&mut self, s: &str) -> Result { | |
| self.buf.write_str(s) | |
| } | |
| fn write_char(&mut self, c: char) -> Result { | |
| self.buf.write_char(c) | |
| } | |
| fn write_fmt(&mut self, args: Arguments) -> Result { | |
| write(self.buf, args) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Display for Error { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Display::fmt("an error occurred when formatting an argument", f) | |
| } | |
| } | |
| // Implementations of the core formatting traits | |
| macro_rules! fmt_refs { | |
| ($($tr:ident),*) => { | |
| $( | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized + $tr> $tr for &T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized + $tr> $tr for &mut T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) } | |
| } | |
| )* | |
| } | |
| } | |
| fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } | |
| #[unstable(feature = "never_type", issue = "35121")] | |
| impl Debug for ! { | |
| fn fmt(&self, _: &mut Formatter) -> Result { | |
| *self | |
| } | |
| } | |
| #[unstable(feature = "never_type", issue = "35121")] | |
| impl Display for ! { | |
| fn fmt(&self, _: &mut Formatter) -> Result { | |
| *self | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Debug for bool { | |
| #[inline] | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Display::fmt(self, f) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Display for bool { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Display::fmt(if *self { "true" } else { "false" }, f) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Debug for str { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.write_char('"')?; | |
| let mut from = 0; | |
| for (i, c) in self.char_indices() { | |
| let esc = c.escape_debug(); | |
| // If char needs escaping, flush backlog so far and write, else skip | |
| if esc.len() != 1 { | |
| f.write_str(&self[from..i])?; | |
| for c in esc { | |
| f.write_char(c)?; | |
| } | |
| from = i + c.len_utf8(); | |
| } | |
| } | |
| f.write_str(&self[from..])?; | |
| f.write_char('"') | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Display for str { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.pad(self) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Debug for char { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.write_char('\'')?; | |
| for c in self.escape_debug() { | |
| f.write_char(c)? | |
| } | |
| f.write_char('\'') | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Display for char { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| if f.width.is_none() && f.precision.is_none() { | |
| f.write_char(*self) | |
| } else { | |
| f.pad(self.encode_utf8(&mut [0; 4])) | |
| } | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Pointer for *const T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| let old_width = f.width; | |
| let old_flags = f.flags; | |
| // The alternate flag is already treated by LowerHex as being special- | |
| // it denotes whether to prefix with 0x. We use it to work out whether | |
| // or not to zero extend, and then unconditionally set it to get the | |
| // prefix. | |
| if f.alternate() { | |
| f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); | |
| if let None = f.width { | |
| f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2); | |
| } | |
| } | |
| f.flags |= 1 << (FlagV1::Alternate as u32); | |
| let ret = LowerHex::fmt(&(*self as *const () as usize), f); | |
| f.width = old_width; | |
| f.flags = old_flags; | |
| ret | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Pointer for *mut T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Pointer::fmt(&(*self as *const T), f) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Pointer for &T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Pointer::fmt(&(*self as *const T), f) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Pointer for &mut T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Pointer::fmt(&(&**self as *const T), f) | |
| } | |
| } | |
| // Implementation of Display/Debug for various core types | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Debug for *const T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Debug for *mut T { | |
| fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } | |
| } | |
| macro_rules! peel { | |
| ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) | |
| } | |
| macro_rules! tuple { | |
| () => (); | |
| ( $($name:ident,)+ ) => ( | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<$($name:Debug),*> Debug for ($($name,)*) where last_type!($($name,)+): ?Sized { | |
| #[allow(non_snake_case, unused_assignments)] | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| let mut builder = f.debug_tuple(""); | |
| let ($(ref $name,)*) = *self; | |
| $( | |
| builder.field(&$name); | |
| )* | |
| builder.finish() | |
| } | |
| } | |
| peel! { $($name,)* } | |
| ) | |
| } | |
| macro_rules! last_type { | |
| ($a:ident,) => { $a }; | |
| ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; | |
| } | |
| tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: Debug> Debug for [T] { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.debug_list().entries(self.iter()).finish() | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Debug for () { | |
| #[inline] | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.pad("()") | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized> Debug for PhantomData<T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.pad("PhantomData") | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: Copy + Debug> Debug for Cell<T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.debug_struct("Cell") | |
| .field("value", &self.get()) | |
| .finish() | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized + Debug> Debug for RefCell<T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| match self.try_borrow() { | |
| Ok(borrow) => { | |
| f.debug_struct("RefCell") | |
| .field("value", &borrow) | |
| .finish() | |
| } | |
| Err(_) => { | |
| // The RefCell is mutably borrowed so we can't look at its value | |
| // here. Show a placeholder instead. | |
| struct BorrowedPlaceholder; | |
| impl Debug for BorrowedPlaceholder { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.write_str("<borrowed>") | |
| } | |
| } | |
| f.debug_struct("RefCell") | |
| .field("value", &BorrowedPlaceholder) | |
| .finish() | |
| } | |
| } | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized + Debug> Debug for Ref<'_, T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Debug::fmt(&**self, f) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl<T: ?Sized + Debug> Debug for RefMut<'_, T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| Debug::fmt(&*(self.deref()), f) | |
| } | |
| } | |
| #[stable(feature = "core_impl_debug", since = "1.9.0")] | |
| impl<T: ?Sized + Debug> Debug for UnsafeCell<T> { | |
| fn fmt(&self, f: &mut Formatter) -> Result { | |
| f.pad("UnsafeCell") | |
| } | |
| } | |
| // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, | |
| // it's a lot easier than creating all of the rt::Piece structures here. |