1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//! Precision trait and predefined precision types for Duration-to-tick conversions.
//!
//! This module provides the foundation for zero-cost abstractions over different
//! time precision scales. The Precision trait enables compile-time optimization
//! of Duration conversions while maintaining type safety and flexibility.
//!
//! # Design Philosophy
//!
//! The precision system allows rate limiters to work with standard Duration
//! while internally using optimized tick representations. Different precision
//! types enable different use cases:
//!
//! - `Nanos`: Maximum precision, suitable for high-frequency operations
//! - `Micros`: Good balance for most applications
//! - `Millis`: Lower precision, suitable for coarse-grained rate limiting
//! - `Secs`: Minimal precision for very long-term rate limiting
//!
//! # Performance
//!
//! All precision conversions use branchless operations that compile to efficient
//! conditional move (CMOV) instructions, avoiding branch prediction penalties.
//!
//! # Examples
//!
//! ```rust
//! use std::time::Duration;
//! use rate_guard::precision::{Precision, Millis, Nanos};
//! use rate_guard::types::Uint;
//! // Convert Duration to ticks using different precisions
//! let duration = Duration::from_millis(100);
//!
//! let millis_ticks = Millis::to_ticks(duration); // 100 ticks
//! let nanos_ticks = Nanos::to_ticks(duration); // 100_000_000 ticks
//!
//! // Convert back to Duration
//! let recovered = Millis::from_ticks(millis_ticks);
//! assert_eq!(recovered, duration);
//!
//! // Generic usage (as used in rate limiters)
//! fn convert_duration<P: Precision>(duration: Duration) -> Uint {
//! P::to_ticks(duration)
//! }
//! ```
use Duration;
use Uint;
/// Trait for defining precision scales for Duration-to-tick conversions.
///
/// Precision implementations define how Duration values are converted to
/// internal tick representations and back. Each precision type represents
/// a different time scale, enabling optimization for different use cases.
///
/// # Implementation Requirements
///
/// Implementations must satisfy these invariants:
/// - Bidirectional conversion consistency: `from_ticks(to_ticks(d)) ≈ d`
/// - Monotonicity: larger durations produce larger tick values
/// - Zero preservation: `to_ticks(Duration::ZERO) == 0`
/// - Overflow handling: graceful saturation on overflow using branchless operations
///
/// # Performance
///
/// All methods should be marked `#[inline(always)]` to enable compile-time
/// optimization and ensure zero-cost abstractions. The `to_ticks` implementation
/// uses branchless min() operations that compile to CMOV instructions for optimal
/// performance.
///
/// # Generic Usage
///
/// The trait is designed to be used with generic type parameters in rate
/// limiters and executors:
///
/// ```rust
/// use std::time::Duration;
/// use rate_guard::precision::{Precision, Millis};
/// use rate_guard::types::Uint;
///
/// fn process_with_precision<P: Precision>(duration: Duration) -> Uint {
/// P::to_ticks(duration) // Static dispatch, zero-cost
/// }
///
/// let ticks = process_with_precision::<Millis>(Duration::from_millis(500));
/// assert_eq!(ticks, 500);
/// ```
/// Nanosecond precision - maximum precision scale.
///
/// Uses 1 tick = 1 nanosecond. This provides the highest precision
/// but may be overkill for many applications. Suitable for:
/// - High-frequency trading systems
/// - Precise timing measurements
/// - Maximum compatibility with system time
///
/// # Overflow Behavior
///
/// Can represent durations up to ~584 years with u64 ticks.
/// Uses branchless saturation on overflow for optimal performance.
;
/// Microsecond precision - high precision scale.
///
/// Uses 1 tick = 1 microsecond. Provides good precision while
/// reducing the range of tick values. Suitable for:
/// - Network latency measurements
/// - General-purpose rate limiting
/// - Applications requiring sub-millisecond precision
///
/// # Overflow Behavior
///
/// Can represent durations up to ~584,000 years with u64 ticks.
/// Uses branchless saturation on overflow for optimal performance.
;
/// Millisecond precision - standard precision scale.
///
/// Uses 1 tick = 1 millisecond. Provides good balance between
/// precision and efficiency. Suitable for:
/// - Web API rate limiting
/// - User-facing applications
/// - Most general-purpose scenarios
///
/// # Overflow Behavior
///
/// Can represent durations up to ~584 million years with u64 ticks.
/// Uses consistent branchless overflow handling for uniformity with other precisions.
;
/// Second precision - coarse precision scale.
///
/// Uses 1 tick = 1 second. Minimal precision but maximum efficiency
/// and range. Suitable for:
/// - Long-term rate limiting (hours, days)
/// - Coarse-grained applications
/// - Memory-constrained environments
///
/// # Overflow Behavior
///
/// Can represent durations far beyond practical limits with u64 ticks.
/// Uses consistent branchless overflow handling for uniformity.
;