#display #formatting #traits #conversion

macro to-display-derive

A trait that is Display or can be converted to Display

2 releases

0.1.2 Dec 29, 2024
0.1.0 Dec 29, 2024

#235 in #formatting

Download history 172/week @ 2024-12-24 19/week @ 2024-12-31

191 downloads per month
Used in to-display

MIT/Apache

7KB

ToDisplay

A zero-allocation library for formatting non-displayable types like Option<T>.

This crate provides the ToDisplay trait which enables customizable string formatting for types that may not implement std::fmt::Display directly.

Quick Example

use to_display::ToDisplay;
use to_display::DisplayConfig;

// Option
println!("{}", Some(1u64).display());                // 1
println!("{}", Some(1u64).display().verbose());      // Some(1)  
println!("{}", None::<u64>.display().verbose());     // None

// Result
println!("{}", Ok::<u64,u32>(1).display());         // Ok(1)
println!("{}", Err::<u64,u32>(2).display());        // Err(2)

// Collection Limits
let vec = vec![1, 2, 3, 4, 5];
println!("{}", vec.display().limit_items(3));       // [1, 2, 3, ...]

// Time Formatting
let time = Instant::now();
println!("{}", time.display());                     // 10:10:10.000000

Features

  • Zero-allocation string formatting
  • Configurable display options (verbose mode, time formats, etc.)
  • Extensive type support including generics and collections
  • Optional time formatting support via feature flags

Supported Types

Primitive Types

The following types implement ToDisplay out of the box:

  • Integers: i8-i128, u8-u128, isize, usize
  • Floating point: f32, f64
  • Other primitives: bool, char, String, &str
  • Network types: IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr
  • Non-zero integers: NonZeroI8-NonZeroU128

Time Types

  • std::time::Instant (requires std-time feature)
let now = Instant::now();
println!("{}", now.display()); // -> "10:10:10.000000"
  • tokio::time::Instant (requires tokio-time feature)
let now = Instant::now();
println!("{}", now.display().use_full_time()); // -> "2024-12-28T23:37:31.646201Z+0800"

Generic Types

  • Option<T> where T: ToDisplay
  • Result<T, E> where T: ToDisplay, E: Display
  • Vec<T> and slices [T] where T: ToDisplay
  • BTreeMap<K, V> where K: ToDisplay, V: ToDisplay

Implementation Methods

Using Derive Macro

For types that already implement Display:

#[derive(to_display::ToDisplay)]
struct Foo(u64);

impl std::fmt::Display for Foo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Foo({})", self.0)
    }
}

Manual Implementation

For types requiring custom display logic or types that don't implement Display, manual implementation of ToDisplay is needed. This involves two steps:

  1. Implement ToDisplay to create a display wrapper type (e.g., DisplayFoo)
  2. Implement Display for the wrapper type to define the formatting logic

Here's a complete example:

use std::fmt;
use to_display::{Context, ToDisplay, DisplayConfig};

struct Foo(u64);

impl ToDisplay for Foo {
    type Displayer<'a> = DisplayFoo<'a>;

    fn display_with_context(&self, context: Context) -> Self::Displayer<'_> {
        DisplayFoo { foo: self, context }
    }
}

struct DisplayFoo<'a> {
    foo: &'a Foo,
    context: Context,
}

impl fmt::Display for DisplayFoo<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Foo({})", self.foo.0)
    }
}

// Optional: Enable display configuration methods
impl<'a> DisplayConfig for DisplayFoo<'a> {
    fn context_mut(&mut self) -> &mut Context {
        &mut self.context
    }
}

assert_eq!(Foo(42).display().to_string(), "Foo(42)");

Feature Flags

  • std-time: Enables support for std::time::Instant
  • tokio-time: Enables support for tokio::time::Instant

Dependencies

~210–640KB
~15K SLoC