summaryrefslogtreecommitdiffstats
path: root/vendor/powerfmt
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/powerfmt
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/powerfmt')
-rw-r--r--vendor/powerfmt/.cargo-checksum.json1
-rw-r--r--vendor/powerfmt/Cargo.toml59
-rw-r--r--vendor/powerfmt/LICENSE-Apache202
-rw-r--r--vendor/powerfmt/LICENSE-MIT19
-rw-r--r--vendor/powerfmt/README.md45
-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
10 files changed, 1591 insertions, 0 deletions
diff --git a/vendor/powerfmt/.cargo-checksum.json b/vendor/powerfmt/.cargo-checksum.json
new file mode 100644
index 000000000..15fec1302
--- /dev/null
+++ b/vendor/powerfmt/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"59fa10abb1a34f70e61c97022938b02ec77ea0b161524f4a2599440bd3190c3b","LICENSE-Apache":"155420c6403d4e0fca34105e3c03fdd6939b64c393c7ec6f95f5b72c5474eab0","LICENSE-MIT":"070dbc7dda03a29296f2d58bdb9b7331af90f2abc9f31df22875d1eabaf29852","README.md":"188fa8a1323086828b9eeaf5a2031d66f066b617fc7dec318835a685d7c2e3c7","src/buf.rs":"b76bcb3daff67ed24e3e5fd958d98565c753107d368c3204ae0d70f9ca7394d4","src/ext.rs":"e6e5063f0006bfe92b59712032d4c6dfe1e1d302d8c92596f3eb7b42f747b9b4","src/lib.rs":"b7a6d061f8d79ed7d78088edefb5946d8eb911b1b523ef849f5f989533955b03","src/smart_display.rs":"44d89db6dbefc1b90e2e3e42279d9ae58f77baeab27a30cafebdb84bfdfaf03c","src/smart_display_impls.rs":"833c5dcb851f7979b222f4736e704ab50bba4d42ef264253dc57237381ef0e5b"},"package":"439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"} \ No newline at end of file
diff --git a/vendor/powerfmt/Cargo.toml b/vendor/powerfmt/Cargo.toml
new file mode 100644
index 000000000..f7acec394
--- /dev/null
+++ b/vendor/powerfmt/Cargo.toml
@@ -0,0 +1,59 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.67.0"
+name = "powerfmt"
+version = "0.2.0"
+authors = ["Jacob Pratt <jacob@jhpratt.dev>"]
+description = """
+ `powerfmt` is a library that provides utilities for formatting values. This crate makes it
+ significantly easier to support filling to a minimum width with alignment, avoid heap
+ allocation, and avoid repetitive calculations.
+"""
+readme = "README.md"
+keywords = [
+ "display",
+ "format",
+ "fmt",
+ "formatter",
+ "extension",
+]
+categories = [
+ "no-std",
+ "no-std::no-alloc",
+ "rust-patterns",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/jhpratt/powerfmt"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "__powerfmt_docs",
+ "--generate-link-to-definition",
+]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies.powerfmt-macros]
+version = "=0.1.0"
+optional = true
+
+[features]
+alloc = []
+default = [
+ "std",
+ "macros",
+]
+macros = ["dep:powerfmt-macros"]
+std = ["alloc"]
diff --git a/vendor/powerfmt/LICENSE-Apache b/vendor/powerfmt/LICENSE-Apache
new file mode 100644
index 000000000..ddde1f9a0
--- /dev/null
+++ b/vendor/powerfmt/LICENSE-Apache
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2023 Jacob Pratt et al.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/powerfmt/LICENSE-MIT b/vendor/powerfmt/LICENSE-MIT
new file mode 100644
index 000000000..89c1f78cb
--- /dev/null
+++ b/vendor/powerfmt/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2023 Jacob Pratt et al.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/powerfmt/README.md b/vendor/powerfmt/README.md
new file mode 100644
index 000000000..c22a3e2fe
--- /dev/null
+++ b/vendor/powerfmt/README.md
@@ -0,0 +1,45 @@
+# `powerfmt`
+
+[![minimum rustc: 1.65](https://img.shields.io/badge/minimum%20rustc-1.65-yellowgreen?logo=rust&style=flat-square)](https://www.whatrustisit.com)
+[![version](https://img.shields.io/crates/v/powerfmt?color=blue&logo=rust&style=flat-square)](https://crates.io/crates/powerfmt)
+[![build status](https://img.shields.io/github/actions/workflow/status/jhpratt/powerfmt/build.yaml?branch=main&style=flat-square)](https://github.com/jhpratt/powerfmt/actions)
+
+Documentation is available [on docs.rs](https://docs.rs/powerfmt).
+
+## Minimum Rust version policy
+
+`powerfmt` is guaranteed to compile with the latest stable release of Rust in addition to the two
+prior minor releases. For example, if the latest stable Rust release is 1.70, then `powerfmt` is
+guaranteed to compile with Rust 1.68, 1.69, and 1.70.
+
+The minimum supported Rust version may be increased to one of the aforementioned versions if doing
+so provides the end user a benefit. However, the minimum supported Rust version may also be bumped
+to a version four minor releases prior to the most recent stable release if doing so improves code
+quality or maintainability.
+
+For interoperability with third-party crates, it is guaranteed that there exists a version of that
+crate that supports the minimum supported Rust version of `powerfmt`. This does not mean that the
+latest version of the third-party crate supports the minimum supported Rust version of `powerfmt`.
+
+## Contributing
+
+Contributions are always welcome! If you have an idea, it's best to float it by me before working on
+it to ensure no effort is wasted. If there's already an open issue for it, knock yourself out.
+
+If you have any questions, feel free to use [Discussions]. Don't hesitate to ask questions — that's
+what I'm here for!
+
+[Discussions]: https://github.com/jhpratt/powerfmt/discussions
+
+## License
+
+This project is licensed under either of
+
+- [Apache License, Version 2.0](https://github.com/jhpratt/powerfmt/blob/main/LICENSE-Apache)
+- [MIT license](https://github.com/jhpratt/powerfmt/blob/main/LICENSE-MIT)
+
+at your option.
+
+Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
+time by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/vendor/powerfmt/src/buf.rs b/vendor/powerfmt/src/buf.rs
new file mode 100644
index 000000000..5a57a60a3
--- /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 000000000..20af7c0aa
--- /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 000000000..0cd6f7cbb
--- /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 000000000..bb55554b8
--- /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 000000000..dc82395f2
--- /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)
+ }
+}