如何打印未实现 Display 或 Debug 的私有类型变量?

问题描述 投票:0回答:2

假设我们有一个无法进行任何更改的私有库,其中包含一些未在库模块中公开的类型。

// lib.rs
mod inner {
    pub struct SecretData {
        value: u32,
    }

    impl SecretData {
        fn new(value: u32) -> Self {
            SecretData { value }
        }
    }

    pub fn create_secret() -> SecretData {
        SecretData::new(42)
    }
}

pub use inner::create_secret;

在我们的应用程序中,我们希望使用库提供的函数创建一个秘密,然后打印出该秘密。

// main.rs
use my_crate::create_secret;


fn main() {
    let secret = create_secret();
    println!("The secret is: {:?}", secret);
}

主函数中的上述代码将导致错误,表明 struct SecretData 尚未实现 Debug 特征。

有什么方法可以打印出

secret
的值吗?

rust private
2个回答
0
投票

一般情况下不可能

为了能够从结构中打印有意义的数据,您需要:

  1. 有可以为您打印的代码,即来自
    std::fmt
    的任何显示特征,或者像
    Path::display
  2. 这样的自定义方法
  3. 或了解
    SecretData
    的内存布局,以便您可以自己安全地阅读和打印它。这排除了所有
    repr(Rust)
    结构。

对于您确实知道其内存布局的结构,您可以转换为确实实现显示特征的结构:

mod inner {
    #[repr(C)]
    pub struct SecretData {
        value: u32,
    }

    impl SecretData {
        fn new(value: u32) -> Self {
            SecretData { value }
        }
    }

    pub fn create_secret() -> SecretData {
        SecretData::new(42)
    }
}

use inner::create_secret;

#[repr(C)]
#[derive(Debug)]
struct NotSoSecret {
    v: u32,
}
fn main() {
    let secret = create_secret();
    // # Safety:
    // Both `SecretData` and `NotSoSecret` are `#[repr(C)]` strutcs with a single `u32` field so they both have the same memory layout.
    println!("The secret is: {:?}", unsafe {
        std::mem::transmute::<_, NotSoSecret>(secret)
    });
}

注意:两者

#[repr(C)]
都是必需的,否则内存布局未指定。


-3
投票

因为您知道

SecretData
的结构,所以可以创建您自己的相同形状的结构和
transmute
您可访问的秘密结构
SpyData
:

pub struct SpyData {
    value: u32,
}

let secret = create_secret();
let spied: SpyData = unsafe { std::mem::transmute(secret) };
println!("The secret is: {}", spied.value);  // 42
© www.soinside.com 2019 - 2024. All rights reserved.