strong_type/
lib.rs

1//! This crate offers a derive macro for crafting strong types in Rust, where a strong type
2//! encapsulates a primitive type, providing a distinct, purpose-specific identity. This pattern
3//! is useful for creating distinct types for distinct purposes. Several macro attributes are
4//! provided to customize the strong type, such as directly implementing arithmetic operators of
5//! the underlying primitive type,
6//!
7//! See the [crate documentation](https://crates.io/crates/strong-type) for more details and examples.
8//!
9
10use std::fmt::Debug;
11
12/// Derive macro to create strong types in Rust.
13pub use strong_type_derive::StrongType;
14
15/// Trait for strong types to obtain the associated underlying type and primitive type.
16pub trait StrongType: Debug + PartialEq + PartialOrd + Clone {
17    type UnderlyingType;
18    type PrimitiveType;
19}
20
21/// Internal module for operator delegation to reduce binary size.
22///
23/// This module provides generic helper functions that are shared across all strong types
24/// wrapping the same primitive type, reducing monomorphization cost.
25#[doc(hidden)]
26pub mod delegation {
27    /// Trait for accessing the underlying primitive value of a strong type.
28    /// This trait is automatically implemented by the StrongType derive macro.
29    pub trait StrongTypeOps: Sized {
30        type Primitive: Copy;
31
32        /// Extract the primitive value from the strong type
33        fn to_primitive(self) -> Self::Primitive;
34
35        /// Create a strong type from a primitive value
36        fn from_primitive(val: Self::Primitive) -> Self;
37    }
38
39    // ============================================================================
40    // Binary Operators - Shared across all strong types per primitive
41    // ============================================================================
42
43    /// Shared add implementation - monomorphized once per primitive type
44    #[inline(never)]
45    pub fn delegate_add<T>(lhs: T, rhs: T) -> T
46    where
47        T: StrongTypeOps,
48        T::Primitive: std::ops::Add<Output = T::Primitive>,
49    {
50        T::from_primitive(lhs.to_primitive() + rhs.to_primitive())
51    }
52
53    /// Shared sub implementation - monomorphized once per primitive type
54    #[inline(never)]
55    pub fn delegate_sub<T>(lhs: T, rhs: T) -> T
56    where
57        T: StrongTypeOps,
58        T::Primitive: std::ops::Sub<Output = T::Primitive>,
59    {
60        T::from_primitive(lhs.to_primitive() - rhs.to_primitive())
61    }
62
63    /// Shared mul implementation - monomorphized once per primitive type
64    #[inline(never)]
65    pub fn delegate_mul<T>(lhs: T, rhs: T) -> T
66    where
67        T: StrongTypeOps,
68        T::Primitive: std::ops::Mul<Output = T::Primitive>,
69    {
70        T::from_primitive(lhs.to_primitive() * rhs.to_primitive())
71    }
72
73    /// Shared div implementation - monomorphized once per primitive type
74    #[inline(never)]
75    pub fn delegate_div<T>(lhs: T, rhs: T) -> T
76    where
77        T: StrongTypeOps,
78        T::Primitive: std::ops::Div<Output = T::Primitive>,
79    {
80        T::from_primitive(lhs.to_primitive() / rhs.to_primitive())
81    }
82
83    /// Shared rem implementation - monomorphized once per primitive type
84    #[inline(never)]
85    pub fn delegate_rem<T>(lhs: T, rhs: T) -> T
86    where
87        T: StrongTypeOps,
88        T::Primitive: std::ops::Rem<Output = T::Primitive>,
89    {
90        T::from_primitive(lhs.to_primitive() % rhs.to_primitive())
91    }
92
93    /// Shared bitand implementation - monomorphized once per primitive type
94    #[inline(never)]
95    pub fn delegate_bitand<T>(lhs: T, rhs: T) -> T
96    where
97        T: StrongTypeOps,
98        T::Primitive: std::ops::BitAnd<Output = T::Primitive>,
99    {
100        T::from_primitive(lhs.to_primitive() & rhs.to_primitive())
101    }
102
103    /// Shared bitor implementation - monomorphized once per primitive type
104    #[inline(never)]
105    pub fn delegate_bitor<T>(lhs: T, rhs: T) -> T
106    where
107        T: StrongTypeOps,
108        T::Primitive: std::ops::BitOr<Output = T::Primitive>,
109    {
110        T::from_primitive(lhs.to_primitive() | rhs.to_primitive())
111    }
112
113    /// Shared bitxor implementation - monomorphized once per primitive type
114    #[inline(never)]
115    pub fn delegate_bitxor<T>(lhs: T, rhs: T) -> T
116    where
117        T: StrongTypeOps,
118        T::Primitive: std::ops::BitXor<Output = T::Primitive>,
119    {
120        T::from_primitive(lhs.to_primitive() ^ rhs.to_primitive())
121    }
122
123    // ============================================================================
124    // Unary Operators
125    // ============================================================================
126
127    /// Shared neg implementation - monomorphized once per primitive type
128    #[inline(never)]
129    pub fn delegate_neg<T>(val: T) -> T
130    where
131        T: StrongTypeOps,
132        T::Primitive: std::ops::Neg<Output = T::Primitive>,
133    {
134        T::from_primitive(-val.to_primitive())
135    }
136
137    /// Shared not implementation - monomorphized once per primitive type
138    #[inline(never)]
139    pub fn delegate_not<T>(val: T) -> T
140    where
141        T: StrongTypeOps,
142        T::Primitive: std::ops::Not<Output = T::Primitive>,
143    {
144        T::from_primitive(!val.to_primitive())
145    }
146
147    // ============================================================================
148    // Bit Shift Operators
149    // ============================================================================
150
151    /// Shared shl implementation - monomorphized once per primitive type
152    #[inline(never)]
153    pub fn delegate_shl<T, Rhs>(lhs: T, rhs: Rhs) -> T
154    where
155        T: StrongTypeOps,
156        T::Primitive: std::ops::Shl<Rhs, Output = T::Primitive>,
157        Rhs: Copy,
158    {
159        T::from_primitive(lhs.to_primitive() << rhs)
160    }
161
162    /// Shared shr implementation - monomorphized once per primitive type
163    #[inline(never)]
164    pub fn delegate_shr<T, Rhs>(lhs: T, rhs: Rhs) -> T
165    where
166        T: StrongTypeOps,
167        T::Primitive: std::ops::Shr<Rhs, Output = T::Primitive>,
168        Rhs: Copy,
169    {
170        T::from_primitive(lhs.to_primitive() >> rhs)
171    }
172
173    // ============================================================================
174    // Scalar Operations
175    // ============================================================================
176
177    /// Shared scalar mul implementation
178    #[inline(never)]
179    pub fn delegate_scalar_mul<T>(lhs: T, rhs: T::Primitive) -> T
180    where
181        T: StrongTypeOps,
182        T::Primitive: std::ops::Mul<Output = T::Primitive>,
183    {
184        T::from_primitive(lhs.to_primitive() * rhs)
185    }
186
187    /// Shared scalar div implementation
188    #[inline(never)]
189    pub fn delegate_scalar_div<T>(lhs: T, rhs: T::Primitive) -> T
190    where
191        T: StrongTypeOps,
192        T::Primitive: std::ops::Div<Output = T::Primitive>,
193    {
194        T::from_primitive(lhs.to_primitive() / rhs)
195    }
196
197    /// Shared scalar rem implementation
198    #[inline(never)]
199    pub fn delegate_scalar_rem<T>(lhs: T, rhs: T::Primitive) -> T
200    where
201        T: StrongTypeOps,
202        T::Primitive: std::ops::Rem<Output = T::Primitive>,
203    {
204        T::from_primitive(lhs.to_primitive() % rhs)
205    }
206}