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.
Apply #[display]
on enum
s:
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"))
}
}
}
}
rustfmt
formats it flawlesslyrust-analyzer
supports hover and goto definition on the actual strings
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 {
/// data store disconnected
Disconnect(std::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,
}
// impl Display omitted since it's identical to the previous section
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("+")
)),
}
}
}
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)
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",
}
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,
}
use thiserror::Error;
use displaydoc::Display;
#[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,
}
#[display]
cannot be applied on generic types likeFoo<T>
, because that significantly increases complexity of the parsing logic required, which also leads to much higher compile-times#[display]
only applies toenum
s