有没有一种方法可以自定义Debug输出而无需直接实现Debug特性?

Ale*_*ara 3 rust

考虑以下代码:

#[derive(Debug)]
struct Test {
    int: u8,
    bits: u8,
    hex: u8
}

fn main() {
    let t = Test {
        int: 1,
        bits: 2,
        hex: 3
    };
    println!("{:#?}", t);
}
Run Code Online (Sandbox Code Playgroud)

运行时,将输出以下内容:

#[derive(Debug)]
struct Test {
    int: u8,
    bits: u8,
    hex: u8
}

fn main() {
    let t = Test {
        int: 1,
        bits: 2,
        hex: 3
    };
    println!("{:#?}", t);
}
Run Code Online (Sandbox Code Playgroud)

可以很轻松地转储结构很酷,但是我的某些数据结构包含位掩码或其他在base 10中不容易读取的数据0b00000010

是否有一种简单的方法来获得这样的输出,而无需Debug直接在struct上实现特征(Debug另一种类型的特征就可以了)?

Test {
    int: 1,
    bits: 2,
    hex: 3
}
Run Code Online (Sandbox Code Playgroud)

如果有必要,我可以使用其他类型,但我希望将struct上的调试特征保持简单#[derive(Debug)]

She*_*ter 5

是否有一种简单的方法来获得这样的输出,而无需Debug直接在struct上实现特征(Debug另一种类型的特征就可以了)

是。#[derive(Debug)]工具Debug通过只调用Debug::debug每个轮流成员。只需按照如何实现自定义'fmt :: Debug'特性的说明进行操作即可。为您的新包装纸。

use std::fmt;

#[derive(Debug)]
struct Test {
    int: u8,
    bits: Bits,
    hex: u8
}

struct Bits(u8);

impl fmt::Debug for Bits {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "0b{:08b}", self.0)
    }
}
Run Code Online (Sandbox Code Playgroud)

在另一个方向上,在主结构上有一个方法可以返回另一个“用于显示目的”结构(类似于),这并不奇怪std::path::Display。这使您可以将复杂的显示逻辑移至单独的类型,同时允许原始结构不包含可能会妨碍您的新类型:

use std::fmt;

impl Test {
    fn pretty_debug(&self) -> PrettyDebug {
        PrettyDebug {
            int: &self.int,
            bits: Bits(&self.bits),
            hex: &self.hex,
        }
    }
}

#[derive(Debug)]
struct PrettyDebug<'a> {
    int: &'a u8,
    bits: Bits<'a>,
    hex: &'a u8
}

struct Bits<'a>(&'a u8);

impl<'a> fmt::Debug for Bits<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "0b{:08b}", self.0)
    }
}
Run Code Online (Sandbox Code Playgroud)

引用到有点傻u8,但是引用是这里最通用的解决方案-为您的案例选择适当的数据类型。

您也可以Debug直接为您的PrettyDebug类型实现:

struct PrettyDebug<'a>(&'a Test);

impl<'a> fmt::Debug for PrettyDebug<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Test")
            .field("int", &self.0.int)
            .field("bits", &format_args!("0b{:08b}", self.0.bits))
            .field("hex", &format_args!("0x{:02x}", self.0.hex))
            .finish()
    }
}
Run Code Online (Sandbox Code Playgroud)