Debug2 is a pretty printing crate based on std::fmt

Related tags

Utilities debug2
Overview

Debug2

debug2 is a pretty printing crate based on std::fmt

Why not just use Debug

The Debug trait is good, but the problem is it is not very good at nested stuctures. Either you use {:?} and get a line that is too long, or too many lines with not enough information on them.

let complex_structure = vec![
    vec![Some(1), Some(2), Some(3), None],
    vec![Some(2), None],
    vec![Some(4), Some(7)],
    vec![Some(1), Some(2), Some(3), None],
];
let one_line = format!("{:?}", complex_structure);
assert_eq!(one_line, "[[Some(1), Some(2), Some(3), None], [Some(2), None], [Some(4), Some(7)], [Some(1), Some(2), Some(3), None]]");
let many_lines = format!("{:#?}", complex_structure);
assert_eq!(many_lines, "[
    [
        Some(
            1,
        ),
        Some(
            2,
        ),
        Some(
            3,
        ),
        None,
    ],
    [
        Some(
            2,
        ),
        None,
    ],
    [
        Some(
            4,
        ),
        Some(
            7,
        ),
    ],
    [
        Some(
            1,
        ),
        Some(
            2,
        ),
        Some(
            3,
        ),
        None,
    ],
]")

debug2 aims to be a third alternative, that gets this correct.

use debug2::pprint;
let complex_structure = vec![
    vec![Some(1), Some(2), Some(3), None],
    vec![Some(2), None],
    vec![Some(4), Some(7)],
    vec![Some(1), Some(2), Some(3), None],
    vec![Some(2), None],
    vec![Some(4), Some(7)],
    vec![Some(1), Some(2), Some(3), None],
    vec![Some(2), None],
    vec![Some(4), Some(7)],
];
assert_eq!(
    pprint(complex_structure),
    "\
[
    [Some(1), Some(2), Some(3), None],
    [Some(2), None],
    [Some(4), Some(7)],
    [Some(1), Some(2), Some(3), None],
    [Some(2), None],
    [Some(4), Some(7)],
    [Some(1), Some(2), Some(3), None],
    [Some(2), None],
    [Some(4), Some(7)],
]"
);

debug2 provides a debug2::Debug trait, which can be derived on your types, and is implemented for common types in std.

Once your types implement debug2::Debug, you can use debug2::pprint to convert them to a string.

You can also manually implement Debug, using a subset of the API in std::fmt::Formatter

Limitations

  • Speed: While doing this will always mean extra work, this crate is paticularly inefficient.
  • Prevalence: Almost every type implements std::fmt::Debug, but not this type
  • The derive isn't great: The derive macro for std::fmt::Debug works everywhere. This one is kind of basic, and will probably not work everywhere it should.

Prior art

  • std::fmt, where much of the code comes from
  • pprint from python , which showed that this sort of thing is doable and great.
  • ojg, whose pretty module is the basis for this whole thing.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Debug2 by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
You might also like...
This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to the arrow format.

Arrow2-derive - derive for Arrow2 This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to th

Tiny Rust crate to iterate bit combinations

bit_combi_iter bit_combi_iter is a small dependency-free crate to enumerate all bit combinations less than given unsigned integer value keeping 1s in

This crate bridges between gstreamer and tracing ecosystems.

This crate provides a bridge between gstreamer and the tracing ecosystem. The goal is to allow Rust applications utilizing GStreamer to better integra

Membrane is an opinionated crate that generates a Dart package from a Rust library. Extremely fast performance with strict typing and zero copy returns over the FFI boundary via bincode.

Membrane is an opinionated crate that generates a Dart package from a Rust library. Extremely fast performance with strict typing and zero copy returns over the FFI boundary via bincode.

Rust crate for reading SER files used in astrophotography

Rust crate for reading SER files used in astrophotography.

A Rust crate for handling URNs.

URN A Rust crate for handling URNs. Parsing and comparison is done according to the spec (meaning only part of the URN is used for equality checks). S

The efficient and elegant crate to count variants of Rust's Enum.

variant-counter The efficient and elegant crate to count variants of Rust's Enum. Get started #[derive(VariantCount)] #[derive(VariantCount)] pub enum

Crate of GitHub’s collection of gitignores, embedded, automatically updated

Gitignores GitHub’s collection of gitignores, embedded, automatically updated. API documentation. Public Domain via CC0-1.0 (same as source data). MSR

This crate allows you to safely initialize Dynamically Sized Types (DST) using only safe Rust.

This crate allows you to safely initialize Dynamically Sized Types (DST) using only safe Rust.

Comments
  • debug2::Debug is not implemented for `str`

    debug2::Debug is not implemented for `str`

    I had a generic pointer that was T: ?Sized and could be str in some cases, where it wouldn't work. I got around this using generic trickery, but it's still not nice

    help wanted needs-MCVE 
    opened by Nilstrieb 3
  • Release v0.1.1

    Release v0.1.1

    Features:

    • dbg! macro
    • More impl for std types

    Right now I'm using git, but I should get arround to releasing these on crates.io. If someone else is using this and wants this, let me know, and I'll be much more likely to do it.

    opened by aDotInTheVoid 1
  • Get string with formatted object

    Get string with formatted object

    I have my own macros for printing stuff on different situations and not putting conditionals everywhere, for example:

    macro_rules! println_on_debug {
        ($($args:tt)*) => {
            if std::env::var("DEBUG").unwrap_or_else(|_| { "false".to_string() }) == "true" ||
               env!("CARGO_PKG_VERSION").ends_with("dev") {
                   println!("DEBUG-MSG: {}", format!{ $($args)* })
            }
        };
    }
    

    I'd like to make that macro print objects with the same formatting as pprint, the problem is that pprint is not a macro that sends args to a formatter and redirects the output to stdout, pprint is a function that just formats & prints a complex structure. My suggestion consists in creating a function that instead of printing the formatted structure to stdout, just returns it, so I can call that macro like this:

    println_on_debug!("struct: {}", pformat(complex_structure));
    
    opened by Alonely0 1
  • Pathological behaviour on deeply nested structures

    Pathological behaviour on deeply nested structures

    use debug2::{pprint, Debug};
    
    use insta::assert_snapshot;
    
    macro_rules! check {
        ($e:expr) => {
            assert_snapshot!(pprint($e))
        };
    }
    
    #[derive(Debug)]
    enum LinkedList<T> {
        Empty,
        Node(T, Box<LinkedList<T>>),
    }
    
    #[test]
    fn linked_list_reasonable_time() {
        let mut list = LinkedList::Empty;
        for i in 0..10000 {
            list = LinkedList::Node(i, Box::new(list));
        }
        check!(list);
    }
    
    thread 'linked_list_reasonable_time' has overflowed its stack
    
    opened by aDotInTheVoid 0
Releases(v0.1.1)
  • v0.1.1(Feb 23, 2022)

    • a662ebcdf2f0438112b7f7961f3a162f469c2ffe: Add dbg! macro to mirror std::dbg!
    • 8b14afb90fc1d9ce470792ea393a9ab821a9e07f: Implement Debug for Box, [T; N], Arc, Rc, *const, *mut

    Full Changelog: https://github.com/aDotInTheVoid/debug2/compare/v0.1...v0.1.1

    Source code(tar.gz)
    Source code(zip)
  • v0.1(Feb 23, 2022)

Owner
Nixon Enraght-Moony
he/him
Nixon Enraght-Moony
🦀 Rust library for printing human readable, relative time differences

?? Rust library for printing human readable, relative time differences

Herbert Lu 31 Aug 6, 2022
single file, std only, async Rust executor

whorl - A single file, std only, async Rust executor whorl was created to teach you how async executors work in Rust. It is not the fastest executor n

Michael Gattozzi 459 Dec 29, 2022
Extent - replacement for std::ops::{Range,RangeInclusive}

extent This is an alternative to std::ops::{Range,RangeInclusive}, avoiding the quirks of those types (non-Copy, inability to produce empty inclusive

Graydon Hoare 33 Sep 27, 2022
dark-std an Implementation of asynchronous containers build on tokio

dark-std dark-std is an Implementation of asynchronous containers build on tokio. It uses a read-write separation design borrowed from Golang SyncHash

darkrpc 4 Dec 13, 2022
no-std no-alloc Rust protobufs.

noproto No-std, no-alloc protocol buffers (protobuf) implementation in Rust, for embedded systems. Optimized for binary size and memory usage, not for

null 13 Jun 21, 2023
Rust crate which provides direct access to files within a Debian archive

debarchive This Rust crate provides direct access to files within a Debian archive. This crate is used by our debrep utility to generate the Packages

Pop!_OS 11 Dec 18, 2021
microtemplate - A fast, microscopic helper crate for runtime string interpolation.

microtemplate A fast, microscopic helper crate for runtime string interpolation. Design Goals Very lightweight: I want microtemplate to do exactly one

_iPhoenix_ 13 Jan 31, 2022
A fancy diagnostics & error reporting crate

A fancy diagnostics & error reporting crate

Joshua Barretto 1.1k Dec 30, 2022
Granular locking crate for Rust

Granular locking crate for Rust. Instead of using coarse-grained Mutex or RwLock which can be used to lock an entire structure, glock provides more granular locking.

Ayman Madkour 9 Jul 22, 2022
A crate to implement leader election for Kubernetes workloads in Rust.

Kubernetes Leader Election in Rust This library provides simple leader election for Kubernetes workloads.

Hendrik Maus 33 Dec 29, 2022