summaryrefslogtreecommitdiffstats
path: root/third_party/rust/displaydoc/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/displaydoc/src/lib.rs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/displaydoc/src/lib.rs')
-rw-r--r--third_party/rust/displaydoc/src/lib.rs187
1 files changed, 187 insertions, 0 deletions
diff --git a/third_party/rust/displaydoc/src/lib.rs b/third_party/rust/displaydoc/src/lib.rs
new file mode 100644
index 0000000000..e4653d6755
--- /dev/null
+++ b/third_party/rust/displaydoc/src/lib.rs
@@ -0,0 +1,187 @@
+//! This library provides a convenient derive macro for the standard library's
+//! [`core::fmt::Display`] trait.
+//!
+//! [`core::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
+//!
+//! ```toml
+//! [dependencies]
+//! displaydoc = "0.2"
+//! ```
+//!
+//! *Compiler support: requires rustc 1.56+*
+//!
+//! <br>
+//!
+//! ## Example
+//!
+//! *Demonstration alongside the [`Error`][std::error::Error] derive macro from [`thiserror`](https://docs.rs/thiserror/1.0.25/thiserror/index.html),
+//! to propagate source locations from [`io::Error`][std::io::Error] with the `#[source]` attribute:*
+//! ```rust
+//! use std::io;
+//! use displaydoc::Display;
+//! use thiserror::Error;
+//!
+//! #[derive(Display, Error, Debug)]
+//! pub enum DataStoreError {
+//! /// data store disconnected
+//! Disconnect(#[source] io::Error),
+//! /// the data for key `{0}` is not available
+//! Redaction(String),
+//! /// invalid header (expected {expected:?}, found {found:?})
+//! InvalidHeader {
+//! expected: String,
+//! found: String,
+//! },
+//! /// unknown data store error
+//! Unknown,
+//! }
+//!
+//! let error = DataStoreError::Redaction("CLASSIFIED CONTENT".to_string());
+//! assert!("the data for key `CLASSIFIED CONTENT` is not available" == &format!("{}", error));
+//! ```
+//! *Note that although [`io::Error`][std::io::Error] implements `Display`, we do not add it to the
+//! generated message for `DataStoreError::Disconnect`, since it is already made available via
+//! `#[source]`. See further context on avoiding duplication in error reports at the rust blog
+//! [here](https://github.com/yaahc/blog.rust-lang.org/blob/master/posts/inside-rust/2021-05-15-What-the-error-handling-project-group-is-working-towards.md#duplicate-information-issue).*
+//!
+//! <br>
+//!
+//! ## Details
+//!
+//! - A `fmt::Display` impl is generated for your enum if you provide
+//! a docstring comment on each variant as shown above in the example. The
+//! `Display` derive macro supports a shorthand for interpolating fields from
+//! the error:
+//! - `/// {var}` ⟶ `write!("{}", self.var)`
+//! - `/// {0}` ⟶ `write!("{}", self.0)`
+//! - `/// {var:?}` ⟶ `write!("{:?}", self.var)`
+//! - `/// {0:?}` ⟶ `write!("{:?}", self.0)`
+//! - This also works with structs and [generic types][crate::Display#generic-type-parameters]:
+//! ```rust
+//! # use displaydoc::Display;
+//! /// oh no, an error: {0}
+//! #[derive(Display)]
+//! pub struct Error<E>(pub E);
+//!
+//! let error: Error<&str> = Error("muahaha i am an error");
+//! assert!("oh no, an error: muahaha i am an error" == &format!("{}", error));
+//! ```
+//!
+//! - Two optional attributes can be added to your types next to the derive:
+//!
+//! - `#[ignore_extra_doc_attributes]` makes the macro ignore any doc
+//! comment attributes (or `///` lines) after the first. Multi-line
+//! comments using `///` are otherwise treated as an error, so use this
+//! attribute or consider switching to block doc comments (`/** */`).
+//!
+//! - `#[prefix_enum_doc_attributes]` combines the doc comment message on
+//! your enum itself with the messages for each variant, in the format
+//! “enum: variant”. When added to an enum, the doc comment on the enum
+//! becomes mandatory. When added to any other type, it has no effect.
+//!
+//! - In case you want to have an independent doc comment, the
+//! `#[displaydoc("...")` atrribute may be used on the variant or struct to
+//! override it.
+//!
+//! <br>
+//!
+//! ## FAQ
+//!
+//! 1. **Is this crate `no_std` compatible?**
+//! * Yes! This crate implements the [`core::fmt::Display`] trait, not the [`std::fmt::Display`] trait, so it should work in `std` and `no_std` environments. Just add `default-features = false`.
+//!
+//! 2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?**
+//! * Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) to add a special trait for types to get the display impl. It then specializes for `Path` and `PathBuf`, and when either of these types are found, it calls `self.display()` to get a `std::path::Display<'_>` type which can be used with the `Display` format specifier!
+#![doc(html_root_url = "https://docs.rs/displaydoc/0.2.3")]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![warn(
+ rust_2018_idioms,
+ unreachable_pub,
+ bad_style,
+ dead_code,
+ improper_ctypes,
+ non_shorthand_field_patterns,
+ no_mangle_generic_items,
+ overflowing_literals,
+ path_statements,
+ patterns_in_fns_without_body,
+ private_in_public,
+ unconditional_recursion,
+ unused,
+ unused_allocation,
+ unused_comparisons,
+ unused_parens,
+ while_true
+)]
+#![allow(clippy::try_err)]
+
+#[allow(unused_extern_crates)]
+extern crate proc_macro;
+
+mod attr;
+mod expand;
+mod fmt;
+
+use proc_macro::TokenStream;
+use syn::{parse_macro_input, DeriveInput};
+
+/// [Custom `#[derive(...)]` macro](https://doc.rust-lang.org/edition-guide/rust-2018/macros/custom-derive.html)
+/// for implementing [`fmt::Display`][core::fmt::Display] via doc comment attributes.
+///
+/// ### Generic Type Parameters
+///
+/// Type parameters to an enum or struct using this macro should *not* need to
+/// have an explicit `Display` constraint at the struct or enum definition
+/// site. A `Display` implementation for the `derive`d struct or enum is
+/// generated assuming each type parameter implements `Display`, but that should
+/// be possible without adding the constraint to the struct definition itself:
+/// ```rust
+/// use displaydoc::Display;
+///
+/// /// oh no, an error: {0}
+/// #[derive(Display)]
+/// pub struct Error<E>(pub E);
+///
+/// // No need to require `E: Display`, since `displaydoc::Display` adds that implicitly.
+/// fn generate_error<E>(e: E) -> Error<E> { Error(e) }
+///
+/// assert!("oh no, an error: muahaha" == &format!("{}", generate_error("muahaha")));
+/// ```
+///
+/// ### Using [`Debug`][core::fmt::Debug] Implementations with Type Parameters
+/// However, if a type parameter must instead be constrained with the
+/// [`Debug`][core::fmt::Debug] trait so that some field may be printed with
+/// `{:?}`, that constraint must currently still also be specified redundantly
+/// at the struct or enum definition site. If a struct or enum field is being
+/// formatted with `{:?}` via [`displaydoc`][crate], and a generic type
+/// parameter must implement `Debug` to do that, then that struct or enum
+/// definition will need to propagate the `Debug` constraint to every type
+/// parameter it's instantiated with:
+/// ```rust
+/// use core::fmt::Debug;
+/// use displaydoc::Display;
+///
+/// /// oh no, an error: {0:?}
+/// #[derive(Display)]
+/// pub struct Error<E: Debug>(pub E);
+///
+/// // `E: Debug` now has to propagate to callers.
+/// fn generate_error<E: Debug>(e: E) -> Error<E> { Error(e) }
+///
+/// assert!("oh no, an error: \"cool\"" == &format!("{}", generate_error("cool")));
+///
+/// // Try this with a struct that doesn't impl `Display` at all, unlike `str`.
+/// #[derive(Debug)]
+/// pub struct Oh;
+/// assert!("oh no, an error: Oh" == &format!("{}", generate_error(Oh)));
+/// ```
+#[proc_macro_derive(
+ Display,
+ attributes(ignore_extra_doc_attributes, prefix_enum_doc_attributes, displaydoc)
+)]
+pub fn derive_error(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ expand::derive(&input)
+ .unwrap_or_else(|err| err.to_compile_error())
+ .into()
+}