rustmacrostraits

Implement trait on all unsigned integers through a macro


I've been writing a data storage module as a technical exercise to get a handle on some fundamental Rust, but I'm running into some problems implementing a trait to translate different types to and from a string that can be stored in a text file. Taking the example of unsigned integers, I was originally going to implement it as follows:

impl<T: num_traits::sign::Unsigned> DataFormatting for T {
    fn as_str_data(&self) -> String {
        format!("{}", *self)
    }

    fn from_str_data(string_data: String) -> T {
        string_data.parse::<T>().unwrap()
    }
}

However, since I previously implemented DataFormatting on String, Rust warns of conflicting implementations to String since "upstream crates may add a new impl of trait 'num_traits::Unsigned' for type 'std::string::String' in future versions". After some research it looked like to support future compatibility I'd be better off automating the listing of related types with a macro but, being new to Rust, I'm not sure how I'd do that in a way that wouldn't be too awkward.


Solution

  • You can do that with a macro like this:

    macro_rules! impl_DataFormatting {
        ( $($type:ty),* $(,)? ) => {
            $(
                impl DataFormatting for $type {
                    fn as_str_data(&self) -> String {
                        format!("{}", *self)
                    }
                
                    fn from_str_data(string_data: String) -> Self {
                        string_data.parse::<Self>().unwrap()
                    }
                }
            )*
        };
    }
    
    impl_DataFormatting!(u8, u16, u32, u64, u128, usize);