当前位置: 首页 > 知识库问答 >
问题:

有没有一种方法可以在不直接实现调试特性的情况下自定义调试输出?

司空思聪
2023-03-14

考虑下面的代码:

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

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

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

Test {
    int: 1,
    bits: 2,
    hex: 3
}

这很酷,我们可以很容易地转储一个结构,但是我的一些数据结构包含位掩码或其他不容易在基数10中读取的数据。对于位字段,读取它会更容易,它们的输出类似于0b00000010

有没有一种简单的方法可以获得这样的输出,而不直接在结构上实现Debugtrait(在另一种类型上实现Debugtrait就可以了)?

Test {
    int: 1,
    bits: 0b00000010,
    hex: 0x03
}

如果有必要,我可以使用不同的类型,但是我希望保持结构本身的调试特性像#[派生(调试)]一样简单。

共有1个答案

全丰
2023-03-14

有没有一种简单的方法可以获得这样的输出,而不需要直接在结构上实现Debug特性(在另一种类型上使用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)
    }
}

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

use std::fmt;

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

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 fmt::Debug for Bits<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "0b{:08b}", self.0)
    }
}

引用一个u8有点傻,但是引用是这里最通用的解决方案-

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

use std::fmt;

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

impl Test {
    fn pretty_debug(&self) -> PrettyDebug<'_> {
        PrettyDebug(self)
    }
}

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

impl fmt::Debug for PrettyDebug<'_> {
    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()
    }
}
 类似资料:
  • 问题内容: 如果通过创建缓冲区,则该内存将位于Java堆之外。有没有一种方法可以以跨平台的方式测量应用程序中此类内存的使用情况,类似于我可以使用and 来测量Java堆使用情况的方法? 问题答案: 您可以使用反射来获取Java 7的OpenJDK / HotSpot。没有独立于平台的方式,它仅通过ByteBuffer.allocateDirect()向您显示用法,而没有其他分配本地内存的方式。 另

  • <代码> 当字母数量增加并离开该区域时,是否有办法自动减小字体大小而不是css溢出?

  • 问题内容: 我刚刚收到Java更新通知,说Update 17已经发布,所以我运行了更新,发现只有我的公共JRE被更新了。我仍然只有JDK的Update 16。 有没有办法自动提供最新的JDK? 当然,更新不应该放弃旧版本。这应该手动完成,因为Eclipse仍在使用旧版本。更新设置后,我将手动删除旧的JDK。 问题答案: 不在Windows上。如果要通过带有自动更新程序的Linux发行版来获取JDK

  • 我想在我的spring web应用程序中添加几个过滤器,但至少现在不会有任何关于安全性的内容。所以。没有spring-security我所能做的就是在web.xml中定义多个过滤器(定义过滤器的旧方法)。要能够使用spring过滤器链,我需要为我的项目添加spring-security作为依赖项,这似乎很奇怪。也许我做错了什么,而且确实有过滤器链可以在没有spring-security依赖的情况下

  • 问题内容: 有没有一种方法可以使用Json.NET序列化器而不使用属性来忽略仅获取属性? 例如,我有一个带有以下get属性的类: 我是否需要添加所有这些属性(我也有许多其他类),还是有更好的方法来忽略所有仅获取属性? 问题答案: 您可以通过实现自定义并在序列化过程中使用它来实现。如果将子类化,这将变得非常容易: 这是一个演示如何使用它的测试程序: 这是上面的输出。请注意,只读属性未包含在输出中。

  • 问题内容: 关于将行旋转为各种数据库的列,有很多文章。他们似乎分为两个阵营,使用案例陈述或使用数据库供应商的内置功能。我正在使用 MySQL ,到目前为止,在任何内置函数上都找不到任何东西,这将使我能够选择任意数量的行值(我想将其转换为列)。如果我不提前知道这些值,则无法构建经常出现在的CASE查询。我想知道在MySQL中是否有类似于其他数据库中称为交叉表或数据透视表的东西: -Postgresq