lorinet3
lorinet3

Reputation: 442

Rust struct field str slice with size

I can do the following:

#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
struct Test {
    field: [u8; 8],
}

But I want to format it as a string when I'm using the debug formatter, and I'm wondering if I could define the field as a str slice with a known size. I can't use String because I am loading the struct from memory, where it is not instantiated by my Rust program. I have read that string slices are represented using UTF-8 characters, but I need ASCII. Should I manually implement the Debug trait instead?

Upvotes: 1

Views: 764

Answers (1)

isaactfa
isaactfa

Reputation: 6651

There's no automatic way of doing that, so you'll have to manually implement Debug. Be careful, however, that not every [u8; 8] is valid UTF-8 (unless you're actually guaranteed to get ASCII).

To be safe, you could switch whether to print field as a string or as an array of bytes based on whether it's legal UTF-8:

use std::fmt;

impl fmt::Debug for Test {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let utf8;
        let value: &dyn fmt::Debug = if let Ok(s) = std::str::from_utf8(&self.field) {
            utf8 = s;
            &utf8
        } else {
            &self.field
        };
        f.debug_struct("Test")
            .field("field", value)
            .finish()
    }
}

fn main() {
    let valid_ascii = Test {
        field: [b'a'; 8],
    };
    let invalid_ascii = Test {
        field: [0xFF; 8],
    };
    println!("{:?}", valid_ascii);   // Test { field: "aaaaaaaa" }
    println!("{:?}", invalid_ascii); // Test { field: [255, 255, 255, 255, 255, 255, 255, 255] }
}

If you're guaranteed valid ASCII, you can of course just use std::str::from_utf8_unchecked and skip that step.

Upvotes: 4

Related Questions