Crate display_as_debug

Crate display_as_debug 

Source
Expand description

§display_as_debug

Build Docs dependency status Crates.io codecov GitHub License

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 DisplayDebug 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.

§Examples

§Basic Usage - Display as Debug Wrappers

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 crate’s .pipe() and conv methods works great:

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 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

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:

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:

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.

Modules§

fmt
Extension traits for Debug builder types. Extension traits for fmt::Debug* builder types.
types
Helper types that implement Debug and/or Display for specialized formatting. Types that implement Debug for specialized formatting.
wrap
Wrapper types for Debug and Display format conversions. Wrapper types for Debug and Display formatting.