# `display_as_debug`
[](https://github.com/MaxMahem/display_as_debug/actions/workflows/build.yml)
[](https://MaxMahem.github.io/display_as_debug/display_as_debug/index.html)
[](https://deps.rs/repo/github/MaxMahem/display_as_debug)
[](https://crates.io/crates/display_as_debug)
[](https://codecov.io/github/MaxMahem/display_as_debug)

A lightweight utility crate with wrappers that let you swap `Display` and `Debug` implementations around.
This crate provides a number of utility types, including adaptors for using a type's `Display` implementation as its `Debug` implementation (and vice versa). It's useful when you need human-readable output in debug contexts, want to return friendly error messages from `main()`, or need to work with types that only implement one trait but you need the other.
This crate is `no_std` compatible and contains no `unsafe` code.
## Features
- **Formatting Wrappers** `wrap` module provides:
- `DisplayAsDebug`, `DebugAsDisplay` for swapping `Display` ↔ `Debug` implementations
- Specialized wrappers for `Option<T>` and `Result<T, E>` that work without requiring `T: Debug`
- Obscuring `Option`/`Result` wrappers for obscuring values while preserving variant information
- **`DebugXXX` extensions** `fmt` module provides extensions for conveniently formatting `std::fmt` `DebugXXX` debug helper types
- **Various Format Types** `types` module provides types for providing information for `Debug` and `Display`
## Installation
It's on [crates.io](https://crates.io/crates/display_as_debug).
## Examples
### Basic Usage - Display as Debug Wrappers
```rust
use display_as_debug::types::TestValue;
use display_as_debug::wrap::DisplayAsDebug;
use display_as_debug::wrap::DebugAsDisplay;
// `TestValue` implements both `Display` and `Debug`, but with different output.
assert_eq!(format!("{}", TestValue::TEST), r#"Display("test")"#, "Should be Display");
assert_eq!(format!("{:?}", TestValue::TEST), r#"Debug("test")"#, "Should be Debug");
assert_eq!(
format!("{:?}", DisplayAsDebug(&TestValue::TEST)),
r#"Display("test")"#,
"Should be Display in Debug context"
);
assert_eq!(
format!("{}", DebugAsDisplay(&TestValue::TEST)),
r#"Debug("test")"#,
"Should be Debug in Display context"
);
// All wrappers implement From, so you can use .into()
let wrapped: DisplayAsDebug<_> = TestValue::DEFAULT.into();
assert_eq!(format!("{:?}", wrapped), "Display(())");
```
> **Tip**: For ergonomic chaining, the [`tap`](https://crates.io/crates/tap) crate's `.pipe()` and `conv` methods works great:
>
> ```rust,ignore
> use tap::{Pipe, Conv};
>
> let display_as_debug = value.pipe(DisplayAsDebug);
> let display_as_debug = value.conv::<DisplayAsDebug>();
> ```
### Returning Friendly Errors from `main()`
When `main()` returns a `Result<(), E>`, Rust prints errors using their `Debug` implementation, which can be verbose and technical. Use `DisplayAsDebug` to show user-friendly error messages instead:
See [examples/error_from_main.rs](examples/error_from_main.rs) for a complete working example.
## Debug extensions
The `fmt` module contains extension traits for the various `std::fmt` `DebugXXX` helper types to extend their functionality.
### `DebugStructExt`
```rust
use display_as_debug::fmt::DebugStructExt;
use display_as_debug::types::{Short, Full};
use std::fmt::{Formatter, Debug};
struct Secret {
id: u32,
key: &'static str,
payload: Vec<u8>,
}
impl Debug for Secret {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Secret")
.field_display("id", &self.id)
.field_opaque("key")
.field_type::<Vec<u8>, Short>("payload")
.finish()
}
}
let secret = Secret { id: 42, key: "secret", payload: vec![1, 2, 3] };
assert_eq!(format!("{:?}", secret), "Secret { id: 42, key: .., payload: Vec<u8> }");
```
`DebugTupleExt` has a similar API. Similar, but more limited extension exist for `DebugList`, `DebugSet`, and `DebugMap`
## Option and Result Wrappers
The `wrap` module also provides wrappers for `Option` and `Result` types that work without requiring `T: Debug`.
### Type Name Wrappers
Show the type name instead of the actual value:
```rust
use display_as_debug::wrap::TypeNameOption;
use display_as_debug::wrap::TypeNameResult;
use display_as_debug::types::{Full, Short};
assert_eq!(
format!("{:?}", TypeNameOption::new::<Full>(Some(42))),
"Some(i32)"
);
let ok: Result<String, i32> = Ok("secret".to_string());
assert_eq!(
format!("{:?}", TypeNameResult::new::<Full>(ok.as_ref())),
"Ok(&alloc::string::String)"
);
assert_eq!(
format!("{:?}", TypeNameResult::new::<Short>(ok.as_ref())),
"Ok(String)"
);
let err: Result<String, i32> = Err(42);
assert_eq!(
format!("{:?}", TypeNameResult::new::<Full>(err.as_ref())),
"Err(42)"
);
```
### Opaque Wrappers
Hide the value completely while preserving the variant information:
```rust
use display_as_debug::wrap::OpaqueOption;
use display_as_debug::wrap::OpaqueResult;
let opt = Some("sensitive data");
assert_eq!(format!("{:?}", OpaqueOption(opt)), "Some(..)");
let res: Result<&str, &str> = Ok("secret");
assert_eq!(format!("{:?}", OpaqueResult(res)), "Ok(..)");
// Errors are still shown for debugging
let err: Result<&str, &str> = Err("connection failed");
assert_eq!(format!("{:?}", OpaqueResult(err)), r#"Err("connection failed")"#);
```
## Debug Formatting Types
The `types` module provides a set of types that can be used to convey various debug formatting information, such as type names, opaque values, and lists.