diff --git a/README.md b/README.md index 3e69e9a..a217814 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ println!("{}", timestamp); // Timestamp(1701620628123456789) - **Derive trait `StrongType`:** Create a named strong type. - The macro automatically implement common traits like `Clone`, `Debug`, `Default`, `PartialEq`, `PartialOrd`, `Send`, and `Sync`. It also implements `Display` by default, unless overridden by the custom_display attribute. - Conditionally, based on the underlying data type, traits like `Copy`, `Eq`, `Ord`, `Hash` may also be implemented. For primitive data types like `i32` or `bool`, these additional traits will be automatically included. - - Numeric types, both integer and floating-point, also implement constants `MIN`, `MAX`. Additionally, for floating-point types, the method `nan()` is implemented. + - Numeric types, both integer and floating-point, also implement constants `MIN`, `MAX`, and `ZERO`. Additionally, for floating-point types, `NAN` is implemented. - **Attributes:** Adding the following attributes to `#[strong_type(...)]` allows for additional features: - `auto_operators`: Automatically implements relevant arithmetic (for numeric types) or logical (for boolean types) operators. diff --git a/strong-type-derive/src/detail/min_max.rs b/strong-type-derive/src/detail/constants.rs similarity index 58% rename from strong-type-derive/src/detail/min_max.rs rename to strong-type-derive/src/detail/constants.rs index 98a42c6..b5b4e76 100644 --- a/strong-type-derive/src/detail/min_max.rs +++ b/strong-type-derive/src/detail/constants.rs @@ -1,11 +1,12 @@ use proc_macro2::TokenStream; use quote::quote; -pub(crate) fn implement_min_max(name: &syn::Ident, value_type: &syn::Ident) -> TokenStream { +pub(crate) fn implement_constants(name: &syn::Ident, value_type: &syn::Ident) -> TokenStream { quote! { impl #name { const MIN: Self = Self(#value_type::MIN); const MAX: Self = Self(#value_type::MAX); + const ZERO: Self = Self(0 as #value_type); } } } diff --git a/strong-type-derive/src/detail/mod.rs b/strong-type-derive/src/detail/mod.rs index 583e28d..e112118 100644 --- a/strong-type-derive/src/detail/mod.rs +++ b/strong-type-derive/src/detail/mod.rs @@ -4,9 +4,9 @@ mod basic_primitive; mod basic_string; mod bit_ops; mod bool_ops; +mod constants; mod display; mod hash; -mod min_max; mod nan; mod negate; mod underlying_type; @@ -18,9 +18,9 @@ pub(crate) use basic_primitive::implement_basic_primitive; pub(crate) use basic_string::implement_basic_string; pub(crate) use bit_ops::implement_bit_shift; pub(crate) use bool_ops::implement_bool_ops; +pub(crate) use constants::implement_constants; pub(crate) use display::implement_display; pub(crate) use hash::implement_hash; -pub(crate) use min_max::implement_min_max; pub(crate) use nan::implement_nan; pub(crate) use negate::implement_negate; pub(crate) use underlying_type::{get_type_group, get_type_ident, UnderlyingTypeGroup}; diff --git a/strong-type-derive/src/detail/nan.rs b/strong-type-derive/src/detail/nan.rs index 19bb237..b5d3721 100644 --- a/strong-type-derive/src/detail/nan.rs +++ b/strong-type-derive/src/detail/nan.rs @@ -4,9 +4,7 @@ use quote::quote; pub(crate) fn implement_nan(name: &syn::Ident, value_type: &syn::Ident) -> TokenStream { quote! { impl #name { - fn nan() -> Self { - Self(#value_type::NAN) - } + const NAN: Self = Self(#value_type::NAN); fn is_nan(&self) -> bool { self.0.is_nan() diff --git a/strong-type-derive/src/strong_type.rs b/strong-type-derive/src/strong_type.rs index 0e18239..71ac51d 100644 --- a/strong-type-derive/src/strong_type.rs +++ b/strong-type-derive/src/strong_type.rs @@ -1,7 +1,7 @@ use crate::detail::{ get_attributes, get_type_group, get_type_ident, implement_arithmetic, implement_basic, implement_basic_primitive, implement_basic_string, implement_bit_shift, implement_bool_ops, - implement_display, implement_hash, implement_min_max, implement_nan, implement_negate, + implement_constants, implement_display, implement_hash, implement_nan, implement_negate, is_struct_valid, StrongTypeAttributes, UnderlyingTypeGroup, }; use proc_macro2::TokenStream; @@ -31,12 +31,12 @@ pub(super) fn expand_strong_type(input: DeriveInput) -> TokenStream { match &group { UnderlyingTypeGroup::Int | UnderlyingTypeGroup::UInt => { ast.extend(implement_basic_primitive(name, value_type)); - ast.extend(implement_min_max(name, value_type)); + ast.extend(implement_constants(name, value_type)); ast.extend(implement_hash(name)); } UnderlyingTypeGroup::Float => { ast.extend(implement_basic_primitive(name, value_type)); - ast.extend(implement_min_max(name, value_type)); + ast.extend(implement_constants(name, value_type)); ast.extend(implement_nan(name, value_type)); } UnderlyingTypeGroup::Bool => { diff --git a/strong-type-tests/tests/strong_type.rs b/strong-type-tests/tests/strong_type.rs index 6664d1d..ee792d8 100644 --- a/strong-type-tests/tests/strong_type.rs +++ b/strong-type-tests/tests/strong_type.rs @@ -96,18 +96,27 @@ mod tests { } #[test] - fn test_min_max() { + fn test_constants() { #[derive(StrongType)] struct Second(i32); assert_eq!(Second::MAX.value(), i32::MAX); assert_eq!(Second::MIN.value(), i32::MIN); + assert_eq!(Second::ZERO.value(), 0i32); #[derive(StrongType)] - struct Meter(f64); + struct State(u8); + + assert_eq!(State::MAX.value(), u8::MAX); + assert_eq!(State::MIN.value(), u8::MIN); + assert_eq!(State::ZERO.value(), 0u8); + + #[derive(StrongType)] + struct Meter(f32); - assert_eq!(Meter::MAX.value(), f64::MAX); - assert_eq!(Meter::MIN.value(), f64::MIN); + assert_eq!(Meter::MAX.value(), f32::MAX); + assert_eq!(Meter::MIN.value(), f32::MIN); + assert_eq!(Meter::ZERO.value(), 0f32); } #[test] @@ -207,7 +216,7 @@ mod tests { #[derive(StrongType)] struct Meter(f64); - let y = Meter::nan(); + let y = Meter::NAN; assert!(y.is_nan()); assert!(y.value().is_nan());