displaystr

This crate provides a convenient attribute macro that implements Display for you
[dependencies]
displaystr = "0.1"
This crate has 0 dependencies. I think compile-times are very important, so I have put a lot of effort into optimizing them.
Example
Apply #[display] on enums:
use displaystr::display;
#[display]
pub enum DataStoreError {
Disconnect(std::io::Error) = "data store disconnected",
Redaction(String) = "the data for key `{_0}` is not available",
InvalidHeader {
expected: String,
found: String,
} = "invalid header (expected {expected:?}, found {found:?})",
Unknown = "unknown data store error",
}
The above expands to this:
use displaystr::display;
pub enum DataStoreError {
Disconnect(std::io::Error),
Redaction(String),
InvalidHeader {
expected: String,
found: String,
},
Unknown,
}
impl ::core::fmt::Display for DataStoreError {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Disconnect(_0) => {
f.write_fmt(format_args!("data store disconnected"))
}
Self::Redaction(_0) => {
f.write_fmt(format_args!("the data for key `{_0}` is not available"))
}
Self::InvalidHeader { expected, found } => {
f.write_fmt(format_args!("invalid header (expected {expected}, found {found})"))
}
Self::Unknown => {
f.write_fmt(format_args!("unknown data store error"))
}
}
}
}
IDE Support
rustfmt formats it flawlessly
rust-analyzer supports hover and goto definition on the actual strings
Auto-generated doc comments
Use #[display(doc)] to automatically generate /// comments:
use displaystr::display;
#[display(doc)]
pub enum DataStoreError {
Disconnect(std::io::Error) = "data store disconnected",
Redaction(String) = "the data for key `{_0}` is not available",
InvalidHeader {
expected: String,
found: String,
} = "invalid header (expected {expected:?}, found {found:?})",
Unknown = "unknown data store error",
}
The above example's expands to this:
use displaystr::display;
pub enum DataStoreError {
Disconnect(std::io::Error),
Redaction(String),
InvalidHeader {
expected: String,
found: String,
},
Unknown,
}
Multiple arguments
You can use a tuple to supply multiple arguments to the format_args!:
use displaystr::display;
#[display]
pub enum DataStoreError {
Redaction(String, Vec<String>) = (
"the data for key `{_0}` is not available, but we recovered: {}",
_1.join("+"),
),
}
Expands to this:
use displaystr::display;
pub enum DataStoreError {
Redaction(String, Vec<String>),
}
impl ::core::fmt::Display for DataStoreError {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Redaction(_0, _1) => f.write_fmt(format_args!(
"the data for key `{_0}` is not available, but we recovered: {}",
_1.join("+")
)),
}
}
}
Comparison between displaystr, thiserror and displaydoc
These 3 errors are identical.
displaystr expresses the same error in the most concise way while being significantly faster to compile (both "cold" compile times, and also each individual invocation)
displaystr
use thiserror::Error;
use displaystr::display;
#[derive(Error, Debug)]
#[display]
pub enum DataStoreError {
Disconnect(#[from] io::Error) = "data store disconnected",
Redaction(String) = "the data for key `{_0}` is not available",
InvalidHeader {
expected: String,
found: String,
} = "invalid header (expected {expected:?}, found {found:?})",
Unknown = "unknown data store error",
}
thiserror
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataStoreError {
#[error("data store disconnected")]
Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
#[error("invalid header (expected {expected:?}, found {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("unknown data store error")]
Unknown,
}
displaydoc
use thiserror::Error;
use displaydoc::Display;
#[derive(Display, Error, Debug)]
pub enum DataStoreError {
Disconnect(#[source] io::Error),
Redaction(String),
InvalidHeader {
expected: String,
found: String,
},
Unknown,
}
Notes
#[display] cannot be applied on generic types like Foo<T>, because that significantly increases
complexity of the parsing logic required, which also leads to much higher compile-times
#[display] only applies to enums
- Variants of enums marked with
#[display] cannot have discriminants