safe_decimal_core 0.1.1

This is a Rust fixed-point numeric library targeting blockchain development. Originally created and used as a part of the Invariant Protocol. The current version leverages macros, traits and generics to exchange dozens of lines of error prone code with a single line and generating the rest.
Documentation
use quote::quote;

use crate::utils::string_to_ident;
use crate::DecimalCharacteristics;

pub fn generate_checked_ops(characteristics: DecimalCharacteristics) -> proc_macro::TokenStream {
    let DecimalCharacteristics { struct_name, .. } = characteristics;

    let name_str = &struct_name.to_string();
    let module_name = string_to_ident("tests_checked_ops_", &name_str);

    proc_macro::TokenStream::from(quote!(
        impl CheckedOps for #struct_name {
            fn checked_add(self, rhs: Self) -> std::result::Result<Self, String> {
                Ok(Self::new(
                    self.get().checked_add(rhs.get())
                    .ok_or_else(|| "checked_add: (self + rhs) additional overflow")?
                ))
            }

            fn checked_sub(self, rhs: Self) -> std::result::Result<Self, String> {
                Ok(Self::new(
                    self.get().checked_sub(rhs.get())
                    .ok_or_else(|| "checked_sub: (self - rhs) subtraction underflow")?
                ))
            }
        }

        #[cfg(test)]
        pub mod #module_name {
            use super::*;

            #[test]
            fn test_checked_add() {
                let a = #struct_name::new(24);
                let b = #struct_name::new(11);

                assert_eq!(a.checked_add(b), Ok(#struct_name::new(35)));
            }

            #[test]
            fn test_overflow_checked_add() {
                let max = #struct_name::max_instance();
                let result = max.checked_add(#struct_name::new(1));

                assert_eq!(result, Err("checked_add: (self + rhs) additional overflow".to_string()));
            }

            #[test]
            fn test_checked_sub() {
                let a = #struct_name::new(35);
                let b = #struct_name::new(11);

                assert_eq!(a.checked_sub(b), Ok(#struct_name::new(24)));
            }

            #[test]
            fn test_underflow_checked_sub() {
                let min = #struct_name::new(0);
                let result = min.checked_sub(#struct_name::new(1));

                assert_eq!(result, Err("checked_sub: (self - rhs) subtraction underflow".to_string()));
            }
        }
    ))
}