'How to make a primitive type parseable and printable differently? [duplicate]

I'm trying to create a new type, which will be i16, but print and parse differently:

use std::fmt;
use std::str::FromStr;

pub type Data = i16;

impl fmt::Display for Data {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "0x{:04X}", self)
    }
}

impl FromStr for Data {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let hex: String = s.chars().skip(2).collect();
        let d = Data::from_str_radix(&hex, 16)
            .expect(&format!("Can't parse hex '{}' in '{}'", hex, s));
        Ok(d)
    }
}

#[test]
pub fn prints_itself() {
    let data : Data = 42;
    assert_eq!("0x003A", format!("{}", data));
}

#[test]
pub fn parses_itself() {
    let data : Data = 42;
    assert_eq!(data, "0x003A".parse());
}

It doesn't compile and I think I understand why. It seems I should declare my type Data somehow differently. How?



Solution 1:[1]

type Foo = Bar doesn't create a new type, it is a "type alias". You can think of it as if the compiler goes and checks for locations of Foo, and replaces them with Bar wherever it is used.

Instead, you want a new type: struct Foo(Bar) and implement any functions/traits you need on the new type.

This is a pretty common pattern, and I have written a library that takes some of the boilerplate out of it, though it is totally optional: https://crates.io/crates/microtype

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cameron1024