https://github.com/alorel/delegate-display-rs
`derive(Display, Debug)` for structs/enums with one member
https://github.com/alorel/delegate-display-rs
Last synced: about 2 months ago
JSON representation
`derive(Display, Debug)` for structs/enums with one member
- Host: GitHub
- URL: https://github.com/alorel/delegate-display-rs
- Owner: Alorel
- License: mit
- Created: 2023-02-28T20:02:48.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-10-28T09:19:50.000Z (6 months ago)
- Last Synced: 2025-02-25T01:31:13.664Z (2 months ago)
- Language: Rust
- Homepage:
- Size: 48.8 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
Lets you derive [`fmt`](https://doc.rust-lang.org/stable/core/fmt/) traits on types wrapping types that already implement them.
[](https://github.com/Alorel/delegate-display-rs/actions/workflows/test.yml?query=branch%3Amaster)
[](https://crates.io/crates/delegate-display)
[](https://coveralls.io/github/Alorel/delegate-display-rs?branch=master)
[](https://libraries.io/cargo/delegate-display)# Examples
Newtype structs```rust
struct SomeType;
impl core::fmt::Display for SomeType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(">foo<")
}
}#[derive(DelegateDisplay)]
struct Foo(SomeType);assert_eq!(format!("{}", Foo(SomeType)), ">foo<");
```Structs with 0..=1 fields
```rust
struct SomeType;
impl core::fmt::Debug for SomeType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(">foo<")
}
}#[derive(DelegateDebug)]
struct Foo { some_field: SomeType }assert_eq!(format!("{:?}", Foo { some_field: SomeType }), ">foo<");
```Enums with 0..=1 variants each
```rust
struct SomeType;
struct AnotherType;impl core::fmt::Display for SomeType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(">foo<")
}
}
impl core::fmt::Display for AnotherType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(">bar<")
}
}#[derive(DelegateDisplay)]
enum MyEnum {
Foo,
Bar(SomeType),
Qux { baz: AnotherType }
}assert_eq!(format!("{}", MyEnum::Bar(SomeType)), ">foo<");
assert_eq!(format!("{}", MyEnum::Qux { baz: AnotherType }), ">bar<");
```Generics
Generics are handled automatically for you.
```rust
#[derive(DelegateDisplay)]
struct MyStruct(T);#[derive(DelegateDisplay)]
enum MyEnum {
A(A),
B { value: B },
}assert_eq!(format!("{}", MyStruct(50)), "50");
assert_eq!(format!("{}", MyEnum::::A(75)), "75");
assert_eq!(format!("{}", MyEnum::::B { value: -1 }), "-1");
```
Structs & enums with 2+ fieldsThe field being delegated to must be marked with the appropriate attribute.
```rust
#[derive(DelegateDisplay)]
struct MyStruct {
label: String,
#[ddisplay]
value: T,
}#[derive(DelegateDebug)]
enum MyEnum {
Foo(#[ddebug] String, u8),
Bar { baz: u8, #[ddebug] qux: u8 }
}let my_struct = MyStruct { label: "foo".into(), value: 42 };
assert_eq!(format!("{}", my_struct), "42");let my_enum = MyEnum::Foo(".".into(), 1);
assert_eq!(format!("{:?}", my_enum), "\".\"");let my_enum = MyEnum::Bar { baz: 2, qux: 3 };
assert_eq!(format!("{:?}", my_enum), "3");
```Empty structs
```rust
#[derive(DelegateDebug, DelegateDisplay)]
struct Foo;#[derive(DelegateDebug, DelegateDisplay)]
struct Bar{}#[derive(DelegateDebug, DelegateDisplay)]
struct Qux();assert_eq!(format!("{}-{:?}", Foo, Foo), "-");
assert_eq!(format!("{}-{:?}", Bar{}, Bar{}), "-");
assert_eq!(format!("{}-{:?}", Qux(), Qux()), "-");
```Typed delegations
Can be useful for further prettifying the output.
```rust
/// Some type that `Deref`s to the type we want to use in our formatting, in this case, `str`.
#[derive(Debug)]
struct Wrapper(&'static str);
impl std::ops::Deref for Wrapper {
type Target = str;
fn deref(&self) -> &Self::Target {
self.0
}
}#[derive(DelegateDebug)]
#[ddebug(delegate_to(str))] // ignore `Wrapper` and debug the `str` it `Deref`s instead
struct Typed(Wrapper);#[derive(DelegateDebug)] // Included for comparison
struct Base(Wrapper);assert_eq!(format!("{:?}", Typed(Wrapper("foo"))), "\"foo\"");
assert_eq!(format!("{:?}", Base(Wrapper("bar"))), "Wrapper(\"bar\")");
```Custom generic bounds
```rust
struct CopyDisplayable(T); // Implements Derefimpl Display for CopyDisplayable {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
unimplemented!("Nonsense generic bound - base bounds don't work.");
}
}// Without these options the implementation would have a predicate of `CopyDisplayable: Debug` which would
// effectively mean `T: Copy`; we can transform it to `T: Display` because `CopyDisplayable` derefs to `T`.
#[derive(DelegateDisplay)]
#[ddisplay(bounds(T: Display), delegate_to(T))]
struct Displayable(CopyDisplayable);let dbg = Displayable::(CopyDisplayable("cdbg".into()));
assert_eq!(format!("{}", dbg), "cdbg");
```Multiple traits at once
Instead of re-parsing your struct/enum multiple times, you can instead derive `DelegateFmt`.
It supports every individual macro's attribute along with `dany` as a catch-all default.```rust
struct Wrapper(u8); // implements Deref#[derive(DelegateFmt)]
#[dfmt(dany(delegate_to(u8)), ddebug, ddisplay, dbinary)]
struct MyStruct(#[dany] Wrapper, #[dbinary] Wrapper);assert_eq!(format!("{:?}", MyStruct::new(1, 2)), "1");
assert_eq!(format!("{}", MyStruct::new(3, 4)), "3");
assert_eq!(format!("{:b}", MyStruct::new(5, 6)), "110");
```Invalid inputs
```rust
#[derive(delegate_display::DelegateDebug)]
struct TooManyFields1 {
foo: u8,
bar: u8, // No fields marked with `#[ddebug]` or `#[dany]`
}
``````rust
#[derive(delegate_display::DelegateDebug)]
struct TooManyFields2(u8, u8); // No fields marked with `#[ddebug]` or `#[dany]`
``````rust
#[derive(delegate_display::DelegateDebug)]
enum SomeEnum {
A, // this is ok
B(u8), // this is ok
C { foo: u8 }, // this is ok
D(u8, u8), // ERR: No fields marked with `#[ddebug]` or `#[dany]`
E { foo: u8, bar: u8 } // ERR: No fields marked with `#[ddebug]` or `#[dany]`
}
``````rust
#[derive(delegate_display::DelegateDebug)]
union Foo { bar: u8 } // Unions are not supported
``````rust
struct NonDebug;#[derive(DelegateDebug)]
struct Foo(A, B);format!("{:?}", Foo(NonDebug, 1)); // NonDebug does not implement Debug
```