summaryrefslogtreecommitdiffstats
path: root/vendor/powerfmt/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/powerfmt/src')
-rw-r--r--vendor/powerfmt/src/buf.rs198
-rw-r--r--vendor/powerfmt/src/ext.rs54
-rw-r--r--vendor/powerfmt/src/lib.rs15
-rw-r--r--vendor/powerfmt/src/smart_display.rs695
-rw-r--r--vendor/powerfmt/src/smart_display_impls.rs303
5 files changed, 1265 insertions, 0 deletions
diff --git a/vendor/powerfmt/src/buf.rs b/vendor/powerfmt/src/buf.rs
new file mode 100644
index 0000000..5a57a60
--- /dev/null
+++ b/vendor/powerfmt/src/buf.rs
@@ -0,0 +1,198 @@
+//! A buffer for constructing a string while avoiding heap allocation.
+
+use core::hash::{Hash, Hasher};
+use core::mem::MaybeUninit;
+use core::{fmt, str};
+
+use crate::smart_display::{FormatterOptions, Metadata, SmartDisplay};
+
+/// A buffer for construct a string while avoiding heap allocation.
+///
+/// The only requirement is that the buffer is large enough to hold the formatted string.
+pub struct WriteBuffer<const SIZE: usize> {
+ buf: [MaybeUninit<u8>; SIZE],
+ len: usize,
+}
+
+impl<const SIZE: usize> fmt::Debug for WriteBuffer<SIZE> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("DisplayBuffer")
+ .field("buf", &self.as_str())
+ .field("remaining_capacity", &self.remaining_capacity())
+ .finish()
+ }
+}
+
+impl<const SIZE: usize> WriteBuffer<SIZE> {
+ /// Creates an empty buffer.
+ pub const fn new() -> Self {
+ Self {
+ buf: maybe_uninit_uninit_array::<_, SIZE>(),
+ len: 0,
+ }
+ }
+
+ /// Obtain the contents of the buffer as a string.
+ pub fn as_str(&self) -> &str {
+ self
+ }
+
+ /// Determine how many bytes are remaining in the buffer.
+ pub const fn remaining_capacity(&self) -> usize {
+ SIZE - self.len
+ }
+}
+
+impl<const SIZE: usize> Default for WriteBuffer<SIZE> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<const LEFT_SIZE: usize, const RIGHT_SIZE: usize> PartialOrd<WriteBuffer<RIGHT_SIZE>>
+ for WriteBuffer<LEFT_SIZE>
+{
+ fn partial_cmp(&self, other: &WriteBuffer<RIGHT_SIZE>) -> Option<core::cmp::Ordering> {
+ self.as_str().partial_cmp(other.as_str())
+ }
+}
+
+impl<const LEFT_SIZE: usize, const RIGHT_SIZE: usize> PartialEq<WriteBuffer<RIGHT_SIZE>>
+ for WriteBuffer<LEFT_SIZE>
+{
+ fn eq(&self, other: &WriteBuffer<RIGHT_SIZE>) -> bool {
+ self.as_str() == other.as_str()
+ }
+}
+
+impl<const SIZE: usize> Eq for WriteBuffer<SIZE> {}
+
+impl<const SIZE: usize> Ord for WriteBuffer<SIZE> {
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ self.as_str().cmp(other.as_str())
+ }
+}
+
+impl<const SIZE: usize> Hash for WriteBuffer<SIZE> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.as_str().hash(state)
+ }
+}
+
+impl<const SIZE: usize> AsRef<str> for WriteBuffer<SIZE> {
+ fn as_ref(&self) -> &str {
+ self
+ }
+}
+
+impl<const SIZE: usize> AsRef<[u8]> for WriteBuffer<SIZE> {
+ fn as_ref(&self) -> &[u8] {
+ self.as_bytes()
+ }
+}
+
+impl<const SIZE: usize> core::borrow::Borrow<str> for WriteBuffer<SIZE> {
+ fn borrow(&self) -> &str {
+ self
+ }
+}
+
+impl<const SIZE: usize> core::ops::Deref for WriteBuffer<SIZE> {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ // SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation which
+ // writes a valid UTF-8 string to `buf` and correctly sets `len`.
+ unsafe {
+ let s = maybe_uninit_slice_assume_init_ref(&self.buf[..self.len]);
+ str::from_utf8_unchecked(s)
+ }
+ }
+}
+
+impl<const SIZE: usize> fmt::Display for WriteBuffer<SIZE> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self)
+ }
+}
+
+impl<const SIZE: usize> SmartDisplay for WriteBuffer<SIZE> {
+ type Metadata = ();
+
+ fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+ Metadata::new(self.len, self, ())
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.pad(self)
+ }
+}
+
+impl<const SIZE: usize> fmt::Write for WriteBuffer<SIZE> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ let bytes = s.as_bytes();
+
+ if let Some(buf) = self.buf.get_mut(self.len..(self.len + bytes.len())) {
+ maybe_uninit_write_slice(buf, bytes);
+ self.len += bytes.len();
+ Ok(())
+ } else {
+ Err(fmt::Error)
+ }
+ }
+}
+
+/// Equivalent of [`MaybeUninit::uninit_array`] that compiles on stable.
+#[must_use]
+#[inline(always)]
+const fn maybe_uninit_uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
+ // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
+ unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
+}
+
+/// Equivalent of [`MaybeUninit::write_slice`] that compiles on stable.
+fn maybe_uninit_write_slice<'a, T>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
+where
+ T: Copy,
+{
+ #[allow(trivial_casts)]
+ // SAFETY: T and MaybeUninit<T> have the same layout
+ let uninit_src = unsafe { &*(src as *const [T] as *const [MaybeUninit<T>]) };
+
+ this.copy_from_slice(uninit_src);
+
+ // SAFETY: Valid elements have just been copied into `this` so it is initialized
+ unsafe { maybe_uninit_slice_assume_init_mut(this) }
+}
+
+/// Equivalent of [`MaybeUninit::slice_assume_init_mut`] that compiles on stable.
+///
+/// # Safety
+///
+/// See [`MaybeUninit::slice_assume_init_mut`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.slice_assume_init_mut).
+#[inline(always)]
+unsafe fn maybe_uninit_slice_assume_init_mut<T, U>(slice: &mut [MaybeUninit<T>]) -> &mut [U] {
+ #[allow(trivial_casts)]
+ // SAFETY: similar to safety notes for `slice_get_ref`, but we have a mutable reference which is
+ // also guaranteed to be valid for writes.
+ unsafe {
+ &mut *(slice as *mut [MaybeUninit<T>] as *mut [U])
+ }
+}
+
+/// Equivalent of [`MaybeUninit::slice_assume_init_ref`] that compiles on stable.
+///
+/// # Safety
+///
+/// See [`MaybeUninit::slice_assume_init_ref`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.slice_assume_init_ref).
+#[inline(always)]
+const unsafe fn maybe_uninit_slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
+ #[allow(trivial_casts)]
+ // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that `slice` is
+ // initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. The pointer
+ // obtained is valid since it refers to memory owned by `slice` which is a reference and thus
+ // guaranteed to be valid for reads.
+ unsafe {
+ &*(slice as *const [MaybeUninit<T>] as *const [T])
+ }
+}
diff --git a/vendor/powerfmt/src/ext.rs b/vendor/powerfmt/src/ext.rs
new file mode 100644
index 0000000..20af7c0
--- /dev/null
+++ b/vendor/powerfmt/src/ext.rs
@@ -0,0 +1,54 @@
+//! Extension traits.
+
+use core::fmt::{Alignment, Arguments, Formatter, Result, Write};
+
+mod sealed {
+ pub trait Sealed {}
+
+ impl Sealed for core::fmt::Formatter<'_> {}
+}
+
+/// An extension trait for [`core::fmt::Formatter`].
+pub trait FormatterExt: sealed::Sealed {
+ /// Writes the given arguments to the formatter, padding them with the given width. If `width`
+ /// is incorrect, the resulting output will not be the requested width.
+ fn pad_with_width(&mut self, width: usize, args: Arguments<'_>) -> Result;
+}
+
+impl FormatterExt for Formatter<'_> {
+ fn pad_with_width(&mut self, args_width: usize, args: Arguments<'_>) -> Result {
+ let Some(final_width) = self.width() else {
+ // The caller has not requested a width. Write the arguments as-is.
+ return self.write_fmt(args);
+ };
+ let Some(fill_width @ 1..) = final_width.checked_sub(args_width) else {
+ // No padding will be present. Write the arguments as-is.
+ return self.write_fmt(args);
+ };
+
+ let alignment = self.align().unwrap_or(Alignment::Left);
+ let fill = self.fill();
+
+ let left_fill_width = match alignment {
+ Alignment::Left => 0,
+ Alignment::Right => fill_width,
+ Alignment::Center => fill_width / 2,
+ };
+ let right_fill_width = match alignment {
+ Alignment::Left => fill_width,
+ Alignment::Right => 0,
+ // When the fill is not even on both sides, the extra fill goes on the right.
+ Alignment::Center => (fill_width + 1) / 2,
+ };
+
+ for _ in 0..left_fill_width {
+ self.write_char(fill)?;
+ }
+ self.write_fmt(args)?;
+ for _ in 0..right_fill_width {
+ self.write_char(fill)?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/powerfmt/src/lib.rs b/vendor/powerfmt/src/lib.rs
new file mode 100644
index 0000000..0cd6f7c
--- /dev/null
+++ b/vendor/powerfmt/src/lib.rs
@@ -0,0 +1,15 @@
+//! `powerfmt` is a library that provides utilities for formatting values. Specifically, it makes it
+//! significantly easier to support filling to a minimum width with alignment, avoid heap
+//! allocation, and avoid repetitive calculations.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(__powerfmt_docs, feature(doc_auto_cfg, rustc_attrs))]
+#![cfg_attr(__powerfmt_docs, allow(internal_features))]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+pub mod buf;
+pub mod ext;
+pub mod smart_display;
+mod smart_display_impls;
diff --git a/vendor/powerfmt/src/smart_display.rs b/vendor/powerfmt/src/smart_display.rs
new file mode 100644
index 0000000..bb55554
--- /dev/null
+++ b/vendor/powerfmt/src/smart_display.rs
@@ -0,0 +1,695 @@
+//! Definition of [`SmartDisplay`] and its related items.
+//!
+//! [`SmartDisplay`] is a trait that allows authors to provide additional information to both the
+//! formatter and other users. This information is provided in the form of a metadata type. The only
+//! required piece of metadata is the width of the value. This is _before_ it is passed to the
+//! formatter (i.e. it does not include any padding added by the formatter). Other information
+//! can be stored in a custom metadata type as needed. This information may be made available to
+//! downstream users, but it is not required.
+//!
+//! This module contains the [`SmartDisplay`] and associated items.
+//!
+//! # Example
+//!
+//! ```rust
+//! use std::fmt;
+//!
+//! use powerfmt::ext::FormatterExt as _;
+//! use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
+//!
+//! #[derive(Debug)]
+//! struct User {
+//! id: usize,
+//! }
+//!
+//! // If you try to use `UserMetadata` in the `SmartDisplay` implementation, you will get a
+//! // compiler error about a private type being used publicly. To avoid this, use this attribute to
+//! // declare a private metadata type. You shouldn't need to worry about how this works, but be
+//! // aware that any public fields or methods remain usable by downstream users.
+//! #[smart_display::private_metadata]
+//! struct UserMetadata {
+//! username: String,
+//! legal_name: String,
+//! }
+//!
+//! // This attribute can be applied to `SmartDisplay` implementations. It will generate an
+//! // implementation of `Display` that delegates to `SmartDisplay`, avoiding the need to write
+//! // boilerplate.
+//! #[smart_display::delegate]
+//! impl SmartDisplay for User {
+//! type Metadata = UserMetadata;
+//!
+//! fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+//! // This could be obtained from a database, for example.
+//! let legal_name = "John Doe".to_owned();
+//! let username = "jdoe".to_owned();
+//!
+//! // Note that this must be kept in sync with the implementation of `fmt_with_metadata`.
+//! let width = smart_display::padded_width_of!(username, " (", legal_name, ")",);
+//!
+//! Metadata::new(
+//! width,
+//! self,
+//! UserMetadata {
+//! username,
+//! legal_name,
+//! },
+//! )
+//! }
+//!
+//! // Use the now-generated metadata to format the value. Here we use the `pad_with_width`
+//! // method to use the alignment and desired width from the formatter.
+//! fn fmt_with_metadata(
+//! &self,
+//! f: &mut fmt::Formatter<'_>,
+//! metadata: Metadata<Self>,
+//! ) -> fmt::Result {
+//! f.pad_with_width(
+//! metadata.unpadded_width(),
+//! format_args!("{} ({})", metadata.username, metadata.legal_name),
+//! )
+//! }
+//! }
+//!
+//! let user = User { id: 42 };
+//! assert_eq!(user.to_string(), "jdoe (John Doe)");
+//! assert_eq!(format!("{user:>20}"), " jdoe (John Doe)");
+//! ```
+
+use core::cmp;
+use core::convert::Infallible;
+use core::fmt::{Alignment, Debug, Display, Formatter, Result};
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+use core::ops::Deref;
+
+/// Compute the width of multiple items while optionally declaring the options for each item.
+///
+/// ```rust
+/// # use powerfmt::smart_display;
+/// let alpha = 0;
+/// let beta = 1;
+/// let gamma = 100;
+///
+/// let width = smart_display::padded_width_of!(
+/// alpha, // use the default options
+/// beta => width(2), // use the specified options
+/// gamma => width(2) sign_plus(true), // use multiple options
+/// );
+/// assert_eq!(width, 7);
+///
+/// let formatted = format!("{alpha}{beta:2}{gamma:+2}");
+/// assert_eq!(formatted.len(), width);
+/// ```
+///
+/// Supported options are:
+///
+/// Option | Method called
+/// --- | ---
+/// `fill(char)` | [`FormatterOptions::with_fill`]
+/// `sign_plus(bool)` | [`FormatterOptions::with_sign_plus`]
+/// `sign_minus(bool)` | [`FormatterOptions::with_sign_minus`]
+/// `align(Alignment)` | [`FormatterOptions::with_align`]
+/// `width(usize)` | [`FormatterOptions::with_width`]
+/// `precision(usize)` | [`FormatterOptions::with_precision`]
+/// `alternate(bool)` | [`FormatterOptions::with_alternate`]
+/// `sign_aware_zero_pad(bool)` | [`FormatterOptions::with_sign_aware_zero_pad`]
+///
+/// If there are future additions to [`FormatterOptions`], they will be added to this macro as well.
+///
+/// Options may be provided in any order and will be called in the order they are provided. The
+/// ordering matters if providing both `sign_plus` and `sign_minus`.
+#[cfg(doc)]
+#[doc(hidden)] // Don't show at crate root.
+#[macro_export]
+macro_rules! padded_width_of {
+ ($($t:tt)*) => {};
+}
+
+#[cfg(not(doc))]
+#[allow(missing_docs)] // This is done with `#[cfg(doc)]` to avoid showing the various rules.
+#[macro_export]
+macro_rules! __not_public_at_root__padded_width_of {
+ // Base case
+ (@inner [] [$($output:tt)+]) => { $($output)+ };
+ (@inner [$e:expr $(, $($remaining:tt)*)?] [$($expansion:tt)+]) => {
+ $crate::smart_display::padded_width_of!(@inner [$($($remaining)*)?] [
+ $($expansion)+ + $crate::smart_display::Metadata::padded_width_of(
+ &$e,
+ $crate::smart_display::padded_width_of!(@options)
+ )
+ ])
+ };
+ (@inner
+ [$e:expr => $($call:ident($call_expr:expr))+ $(, $($remaining:tt)*)?]
+ [$($expansion:tt)+]
+ ) => {
+ $crate::smart_display::padded_width_of!(@inner [$($($remaining)*)?] [
+ $($expansion)+ + $crate::smart_display::Metadata::padded_width_of(
+ &$e,
+ *$crate::smart_display::padded_width_of!(@options $($call($call_expr))+)
+ )
+ ])
+ };
+
+ // Options base case
+ (@options_inner [] [$($output:tt)+]) => { $($output)+ };
+ (@options_inner [fill($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_fill($e)
+ ])
+ };
+ (@options_inner [sign_plus($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_sign_plus($e)
+ ])
+ };
+ (@options_inner [sign_minus($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_sign_minus($e)
+ ])
+ };
+ (@options_inner [align($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_align(Some($e))
+ ])
+ };
+ (@options_inner [width($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_width(Some($e))
+ ])
+ };
+ (@options_inner [precision($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_precision(Some($e))
+ ])
+ };
+ (@options_inner [alternate($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_width($e)
+ ])
+ };
+ (@options_inner [sign_aware_zero_pad($e:expr) $($remaining:tt)*] [$($expansion:tt)*]) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($remaining)*] [
+ $($expansion)*.with_sign_aware_zero_pad($e)
+ ])
+ };
+ // Options entry point
+ (@options $($e:tt)*) => {
+ $crate::smart_display::padded_width_of!(@options_inner [$($e)*] [
+ $crate::smart_display::FormatterOptions::default()
+ ])
+ };
+
+ // Entry point
+ ($($t:tt)*) => {
+ $crate::smart_display::padded_width_of!(
+ @inner [$($t)*] [0]
+ )
+ };
+}
+
+#[cfg(not(doc))]
+pub use __not_public_at_root__padded_width_of as padded_width_of;
+#[cfg(doc)]
+#[doc(inline)] // Show in this module.
+pub use padded_width_of;
+/// Implement [`Display`] for a type by using its implementation of [`SmartDisplay`].
+///
+/// This attribute is applied to the `SmartDisplay` implementation.
+///
+/// ```rust,no_run
+/// # use powerfmt::smart_display::{self, SmartDisplay, Metadata, FormatterOptions};
+/// # struct Foo;
+/// #[smart_display::delegate]
+/// impl SmartDisplay for Foo {
+/// # type Metadata = ();
+/// # fn metadata(&self, f: FormatterOptions) -> Metadata<Self> {
+/// # todo!()
+/// # }
+/// // ...
+/// }
+/// ```
+#[cfg(feature = "macros")]
+pub use powerfmt_macros::smart_display_delegate as delegate;
+/// Declare a private metadata type for `SmartDisplay`.
+///
+/// Use this attribute if you want to provide metadata for a type that is not public. Doing
+/// this will avoid a compiler error about a private type being used publicly. Keep in mind
+/// that any public fields, public methods, and trait implementations _will_ be able to be used
+/// by downstream users.
+///
+/// To avoid accidentally exposing details, such as when all fields are public or if the type
+/// is a unit struct, the type is annotated with `#[non_exhaustive]` automatically.
+///
+/// ```rust,no_run
+/// # use powerfmt::smart_display;
+/// /// Metadata for `Foo`
+/// #[smart_display::private_metadata]
+/// #[derive(Debug)]
+/// pub(crate) struct FooMetadata {
+/// pub(crate) expensive_to_calculate: usize,
+/// }
+/// ```
+#[cfg(feature = "macros")]
+pub use powerfmt_macros::smart_display_private_metadata as private_metadata;
+
+#[derive(Debug)]
+enum FlagBit {
+ SignPlus,
+ SignMinus,
+ Alternate,
+ SignAwareZeroPad,
+ WidthIsInitialized,
+ PrecisionIsInitialized,
+}
+
+/// Configuration for formatting.
+///
+/// This struct is obtained from a [`Formatter`]. It provides the same functionality as that of a
+/// reference to a `Formatter`. However, it is not possible to construct a `Formatter`, which is
+/// necessary for some use cases of [`SmartDisplay`]. `FormatterOptions` implements [`Default`] and
+/// has builder methods to alleviate this.
+#[derive(Clone, Copy)]
+pub struct FormatterOptions {
+ flags: u8,
+ fill: char,
+ align: Option<Alignment>,
+ width: MaybeUninit<usize>,
+ precision: MaybeUninit<usize>,
+}
+
+impl Debug for FormatterOptions {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ f.debug_struct("FormatterOptions")
+ .field("fill", &self.fill)
+ .field("align", &self.align())
+ .field("width", &self.width())
+ .field("precision", &self.precision())
+ .field("sign_plus", &self.sign_plus())
+ .field("sign_minus", &self.sign_minus())
+ .field("alternate", &self.alternate())
+ .field("sign_aware_zero_pad", &self.sign_aware_zero_pad())
+ .finish()
+ }
+}
+
+impl Default for FormatterOptions {
+ #[inline]
+ fn default() -> Self {
+ Self {
+ flags: 0,
+ fill: ' ',
+ align: None,
+ width: MaybeUninit::uninit(),
+ precision: MaybeUninit::uninit(),
+ }
+ }
+}
+
+impl FormatterOptions {
+ /// Sets the fill character to use whenever there is alignment.
+ #[inline]
+ pub fn with_fill(&mut self, c: char) -> &mut Self {
+ self.fill = c;
+ self
+ }
+
+ /// Set whether the `+` flag is specified.
+ #[inline]
+ pub fn with_sign_plus(&mut self, b: bool) -> &mut Self {
+ if b {
+ self.flags |= 1 << FlagBit::SignPlus as u8;
+ self.flags &= !(1 << FlagBit::SignMinus as u8);
+ } else {
+ self.flags &= !(1 << FlagBit::SignPlus as u8);
+ }
+ self
+ }
+
+ /// Set whether the `-` flag is specified.
+ #[inline]
+ pub fn with_sign_minus(&mut self, b: bool) -> &mut Self {
+ if b {
+ self.flags |= 1 << FlagBit::SignMinus as u8;
+ self.flags &= !(1 << FlagBit::SignPlus as u8);
+ } else {
+ self.flags &= !(1 << FlagBit::SignMinus as u8);
+ }
+ self
+ }
+
+ /// Set the flag indicating what form of alignment is requested, if any.
+ #[inline]
+ pub fn with_align(&mut self, align: Option<Alignment>) -> &mut Self {
+ self.align = align;
+ self
+ }
+
+ /// Set the optional integer width that the output should be.
+ #[inline]
+ pub fn with_width(&mut self, width: Option<usize>) -> &mut Self {
+ if let Some(width) = width {
+ self.flags |= 1 << FlagBit::WidthIsInitialized as u8;
+ self.width = MaybeUninit::new(width);
+ } else {
+ self.flags &= !(1 << FlagBit::WidthIsInitialized as u8);
+ }
+ self
+ }
+
+ /// Set the optional precision for numeric types. Alternatively, the maximum width for string
+ /// types.
+ #[inline]
+ pub fn with_precision(&mut self, precision: Option<usize>) -> &mut Self {
+ if let Some(precision) = precision {
+ self.flags |= 1 << FlagBit::PrecisionIsInitialized as u8;
+ self.precision = MaybeUninit::new(precision);
+ } else {
+ self.flags &= !(1 << FlagBit::PrecisionIsInitialized as u8);
+ }
+ self
+ }
+
+ /// Set whether the `#` flag is specified.
+ #[inline]
+ pub fn with_alternate(&mut self, b: bool) -> &mut Self {
+ if b {
+ self.flags |= 1 << FlagBit::Alternate as u8;
+ } else {
+ self.flags &= !(1 << FlagBit::Alternate as u8);
+ }
+ self
+ }
+
+ /// Set whether the `0` flag is specified.
+ #[inline]
+ pub fn with_sign_aware_zero_pad(&mut self, b: bool) -> &mut Self {
+ if b {
+ self.flags |= 1 << FlagBit::SignAwareZeroPad as u8;
+ } else {
+ self.flags &= !(1 << FlagBit::SignAwareZeroPad as u8);
+ }
+ self
+ }
+}
+
+impl FormatterOptions {
+ /// Character used as 'fill' whenever there is alignment.
+ #[inline]
+ #[must_use]
+ pub const fn fill(&self) -> char {
+ self.fill
+ }
+
+ /// Flag indicating what form of alignment was requested.
+ #[inline]
+ #[must_use]
+ pub const fn align(&self) -> Option<Alignment> {
+ self.align
+ }
+
+ /// Optionally specified integer width that the output should be.
+ #[inline]
+ #[must_use]
+ pub const fn width(&self) -> Option<usize> {
+ if (self.flags >> FlagBit::WidthIsInitialized as u8) & 1 == 1 {
+ // Safety: `width` is initialized if the flag is set.
+ Some(unsafe { self.width.assume_init() })
+ } else {
+ None
+ }
+ }
+
+ /// Optionally specified precision for numeric types. Alternatively, the maximum width for
+ /// string types.
+ #[inline]
+ #[must_use]
+ pub const fn precision(&self) -> Option<usize> {
+ if (self.flags >> FlagBit::PrecisionIsInitialized as u8) & 1 == 1 {
+ // Safety: `precision` is initialized if the flag is set.
+ Some(unsafe { self.precision.assume_init() })
+ } else {
+ None
+ }
+ }
+
+ /// Determines if the `+` flag was specified.
+ #[inline]
+ #[must_use]
+ pub const fn sign_plus(&self) -> bool {
+ (self.flags >> FlagBit::SignPlus as u8) & 1 == 1
+ }
+
+ /// Determines if the `-` flag was specified.
+ #[inline]
+ #[must_use]
+ pub const fn sign_minus(&self) -> bool {
+ (self.flags >> FlagBit::SignMinus as u8) & 1 == 1
+ }
+
+ /// Determines if the `#` flag was specified.
+ #[inline]
+ #[must_use]
+ pub const fn alternate(&self) -> bool {
+ (self.flags >> FlagBit::Alternate as u8) & 1 == 1
+ }
+
+ /// Determines if the `0` flag was specified.
+ #[inline]
+ #[must_use]
+ pub const fn sign_aware_zero_pad(&self) -> bool {
+ (self.flags >> FlagBit::SignAwareZeroPad as u8) & 1 == 1
+ }
+}
+
+impl From<&Formatter<'_>> for FormatterOptions {
+ fn from(value: &Formatter<'_>) -> Self {
+ *Self::default()
+ .with_fill(value.fill())
+ .with_sign_plus(value.sign_plus())
+ .with_sign_minus(value.sign_minus())
+ .with_align(value.align())
+ .with_width(value.width())
+ .with_precision(value.precision())
+ .with_alternate(value.alternate())
+ .with_sign_aware_zero_pad(value.sign_aware_zero_pad())
+ }
+}
+
+impl From<&mut Formatter<'_>> for FormatterOptions {
+ #[inline]
+ fn from(value: &mut Formatter<'_>) -> Self {
+ (&*value).into()
+ }
+}
+
+/// Information used to format a value. This is returned by [`SmartDisplay::metadata`].
+///
+/// This type is generic over any user-provided type. This allows the author to store any
+/// information that is needed. For example, a type's implementation of [`SmartDisplay`] may need
+/// to calculate something before knowing its width. This calculation can be performed, with the
+/// result being stored in the custom metadata type.
+///
+/// Note that `Metadata` _always_ contains the width of the type. Authors do not need to store this
+/// information in their custom metadata type.
+///
+/// Generally speaking, a type should be able to be formatted using only its metadata, fields, and
+/// the formatter. Any other information should be stored in the metadata type.
+pub struct Metadata<'a, T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ unpadded_width: usize,
+ metadata: T::Metadata,
+ _value: PhantomData<&'a T>, // variance
+}
+
+// manual impls for bounds
+impl<T> Debug for Metadata<'_, T>
+where
+ T: SmartDisplay,
+ T::Metadata: Debug,
+{
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ f.debug_struct("Metadata")
+ .field("unpadded_width", &self.unpadded_width)
+ .field("metadata", &self.metadata)
+ .finish()
+ }
+}
+
+impl<T> Clone for Metadata<'_, T>
+where
+ T: SmartDisplay,
+ T::Metadata: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ unpadded_width: self.unpadded_width,
+ metadata: self.metadata.clone(),
+ _value: self._value,
+ }
+ }
+}
+
+impl<T> Copy for Metadata<'_, T>
+where
+ T: SmartDisplay,
+ T::Metadata: Copy,
+{
+}
+
+impl<'a, T> Metadata<'a, T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ /// Creates a new `Metadata` with the given width and metadata. While the width _should_ be
+ /// exact, this is not a requirement for soundness.
+ pub const fn new(unpadded_width: usize, _value: &T, metadata: T::Metadata) -> Self {
+ Self {
+ unpadded_width,
+ metadata,
+ _value: PhantomData,
+ }
+ }
+
+ /// Reuse the metadata for another type. This is useful when implementing [`SmartDisplay`] for a
+ /// type that wraps another type. Both type's metadata type must be the same.
+ pub fn reuse<'b, U>(self) -> Metadata<'b, U>
+ where
+ 'a: 'b,
+ U: SmartDisplay<Metadata = T::Metadata> + ?Sized,
+ {
+ Metadata {
+ unpadded_width: self.unpadded_width,
+ metadata: self.metadata,
+ _value: PhantomData,
+ }
+ }
+
+ /// Obtain the width of the value before padding.
+ pub const fn unpadded_width(&self) -> usize {
+ self.unpadded_width
+ }
+
+ /// Obtain the width of the value after padding.
+ pub fn padded_width(&self, f: FormatterOptions) -> usize {
+ match f.width() {
+ Some(requested_width) => cmp::max(self.unpadded_width(), requested_width),
+ None => self.unpadded_width(),
+ }
+ }
+}
+
+impl Metadata<'_, Infallible> {
+ /// Obtain the width of the value before padding, given the formatter options.
+ pub fn unpadded_width_of<T>(value: T, f: FormatterOptions) -> usize
+ where
+ T: SmartDisplay,
+ {
+ value.metadata(f).unpadded_width
+ }
+
+ /// Obtain the width of the value after padding, given the formatter options.
+ pub fn padded_width_of<T>(value: T, f: FormatterOptions) -> usize
+ where
+ T: SmartDisplay,
+ {
+ value.metadata(f).padded_width(f)
+ }
+}
+
+/// Permit using `Metadata` as a smart pointer to the user-provided metadata.
+impl<T> Deref for Metadata<'_, T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Target = T::Metadata;
+
+ fn deref(&self) -> &T::Metadata {
+ &self.metadata
+ }
+}
+
+/// Format trait that allows authors to provide additional information.
+///
+/// This trait is similar to [`Display`], but allows the author to provide additional information
+/// to the formatter. This information is provided in the form of a custom metadata type.
+///
+/// The only required piece of metadata is the width of the value. This is _before_ it is passed to
+/// the formatter (i.e. it does not include any padding added by the formatter). Other information
+/// can be stored in a custom metadata type as needed. This information may be made available to
+/// downstream users, but it is not required.
+///
+/// **Note**: While both `fmt_with_metadata` and `fmt` have default implementations, it is strongly
+/// recommended to implement only `fmt_with_metadata`. `fmt` should be implemented if and only if
+/// the type does not require any of the calculated metadata. In that situation, `fmt_with_metadata`
+/// should be omitted.
+#[cfg_attr(__powerfmt_docs, rustc_must_implement_one_of(fmt, fmt_with_metadata))]
+pub trait SmartDisplay: Display {
+ /// User-provided metadata type.
+ type Metadata;
+
+ /// Compute any information needed to format the value. This must, at a minimum, determine the
+ /// width of the value before any padding is added by the formatter.
+ ///
+ /// If the type uses other types that implement `SmartDisplay` verbatim, the inner types should
+ /// have their metadata calculated and included in the returned value.
+ ///
+ /// # Lifetimes
+ ///
+ /// This method's return type contains a lifetime to `self`. This ensures that the metadata will
+ /// neither outlive the value nor be invalidated by a mutation of the value (barring interior
+ /// mutability).
+ ///
+ /// ```rust,compile_fail
+ /// # use std::fmt;
+ /// # use std::fmt::Write;
+ /// # use powerfmt::buf::WriteBuffer;
+ /// # use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
+ /// #[derive(Debug)]
+ /// struct WrappedBuffer(WriteBuffer<128>);
+ ///
+ /// #[smart_display::delegate]
+ /// impl SmartDisplay for WrappedBuffer {
+ /// type Metadata = ();
+ ///
+ /// fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+ /// Metadata::new(self.0.len(), self, ())
+ /// }
+ ///
+ /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ /// f.pad(self.0.as_str())
+ /// }
+ /// }
+ ///
+ /// let mut buf = WrappedBuffer(WriteBuffer::new());
+ /// let metadata = buf.metadata(FormatterOptions::default());
+ /// // We cannot mutate the buffer while it is borrowed and use its previous metadata on the
+ /// // following line.
+ /// write!(buf.0, "Hello, world!")?;
+ /// assert_eq!(metadata.width(), 13);
+ /// # Ok::<(), Box<dyn std::error::Error>>(())
+ /// ```
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self>;
+
+ /// Format the value using the given formatter and metadata. The formatted output should have
+ /// the width indicated by the metadata. This is before any padding is added by the
+ /// formatter.
+ ///
+ /// If the metadata is not needed, you should implement the `fmt` method instead.
+ fn fmt_with_metadata(&self, f: &mut Formatter<'_>, _metadata: Metadata<'_, Self>) -> Result {
+ SmartDisplay::fmt(self, f)
+ }
+
+ /// Format the value using the given formatter. This is the same as [`Display::fmt`].
+ ///
+ /// The default implementation of this method calls `fmt_with_metadata` with the result of
+ /// `metadata`. Generally speaking, this method should not be implemented. You should implement
+ /// the `fmt_with_metadata` method instead.
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let metadata = self.metadata(f.into());
+ self.fmt_with_metadata(f, metadata)
+ }
+}
diff --git a/vendor/powerfmt/src/smart_display_impls.rs b/vendor/powerfmt/src/smart_display_impls.rs
new file mode 100644
index 0000000..dc82395
--- /dev/null
+++ b/vendor/powerfmt/src/smart_display_impls.rs
@@ -0,0 +1,303 @@
+//! Implementation of [`SmartDisplay`] for various types.
+
+#[cfg(feature = "alloc")]
+use alloc::borrow::{Cow, ToOwned};
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
+#[cfg(feature = "alloc")]
+use alloc::rc::Rc;
+#[cfg(feature = "alloc")]
+use alloc::string::String;
+#[cfg(feature = "alloc")]
+use alloc::sync::Arc;
+use core::cell::{Ref, RefMut};
+use core::cmp::min;
+use core::convert::Infallible;
+use core::fmt::{self, Display, Formatter};
+use core::num::Wrapping;
+use core::pin::Pin;
+
+use crate::smart_display::{FormatterOptions, Metadata, SmartDisplay};
+
+impl SmartDisplay for Infallible {
+ type Metadata = Self;
+
+ #[inline]
+ fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+ match *self {}
+ }
+
+ #[inline]
+ fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result {
+ match *self {}
+ }
+}
+
+impl SmartDisplay for bool {
+ type Metadata = ();
+
+ #[inline]
+ fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+ Metadata::new(if *self { 4 } else { 5 }, self, ())
+ }
+
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+impl SmartDisplay for str {
+ type Metadata = ();
+
+ #[inline]
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ Metadata::new(
+ match f.precision() {
+ Some(max_len) => min(self.len(), max_len),
+ None => self.len(),
+ },
+ self,
+ (),
+ )
+ }
+
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl SmartDisplay for String {
+ type Metadata = ();
+
+ #[inline]
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<'a, B, O> SmartDisplay for Cow<'a, B>
+where
+ B: SmartDisplay + ToOwned<Owned = O> + ?Sized,
+ O: SmartDisplay<Metadata = B::Metadata> + 'a,
+{
+ type Metadata = B::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ match *self {
+ Cow::Borrowed(ref b) => b.metadata(f).reuse(),
+ Cow::Owned(ref o) => o.metadata(f).reuse(),
+ }
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+impl<T> SmartDisplay for Pin<&T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ self.get_ref().metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(self.get_ref(), f)
+ }
+}
+
+impl<T> SmartDisplay for &T
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(*self, f)
+ }
+}
+
+impl<T> SmartDisplay for &mut T
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(*self, f)
+ }
+}
+
+impl<T> SmartDisplay for Ref<'_, T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&**self, f)
+ }
+}
+
+impl<T> SmartDisplay for RefMut<'_, T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&**self, f)
+ }
+}
+
+impl<T> SmartDisplay for Wrapping<T>
+where
+ T: SmartDisplay,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ self.0.metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&self.0, f)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<T> SmartDisplay for Rc<T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&**self, f)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<T> SmartDisplay for Arc<T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&**self, f)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<T> SmartDisplay for Box<T>
+where
+ T: SmartDisplay + ?Sized,
+{
+ type Metadata = T::Metadata;
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ (**self).metadata(f).reuse()
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ SmartDisplay::fmt(&**self, f)
+ }
+}
+
+/// Implement [`SmartDisplay`] for unsigned integers.
+macro_rules! impl_uint {
+ ($($t:ty)*) => {$(
+ impl SmartDisplay for $t {
+ type Metadata = ();
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ let mut width = self.checked_ilog10().map_or(1, |n| n as usize + 1);
+ if f.sign_plus() || f.sign_minus() {
+ width += 1;
+ }
+ Metadata::new(width, self, ())
+ }
+
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+ }
+ )*};
+}
+
+impl_uint![u8 u16 u32 u64 u128 usize];
+
+/// Implement [`SmartDisplay`] for signed integers.
+macro_rules! impl_int {
+ ($($t:ty)*) => {$(
+ impl SmartDisplay for $t {
+ type Metadata = ();
+
+ fn metadata(&self, f: FormatterOptions) -> Metadata<'_, Self> {
+ let mut width = if f.sign_plus() || *self < 0 { 1 } else { 0 };
+ width += self.unsigned_abs().checked_ilog10().map_or(1, |n| n as usize + 1);
+ Metadata::new(width, self, ())
+ }
+
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+ }
+ )*};
+}
+
+impl_int![i8 i16 i32 i64 i128 isize];
+
+impl SmartDisplay for char {
+ type Metadata = ();
+
+ fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
+ let mut buf = [0; 4];
+ let c = self.encode_utf8(&mut buf);
+
+ Metadata::new(c.len(), self, ())
+ }
+
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}