1#![allow(dead_code)]
7
8macro_rules! scast {
13 (all_orig: $($orig:ty),+) => {
14 $( scast![all_dest: $orig; i8, u8, i16, u16, i32, u32, i64, u64, usize, isize]; )+
15 };
16
17 (all_dest: $orig:ty; $($dest:ty),+) => {
18 $( scast![single: $orig, $dest]; )+
19 };
20
21 (single: $orig:ty, $dest:ty) => {
22 paste::paste! {
23 #[doc = "Returns a saturating casted value from " $orig " to " $dest "."]
24 #[inline]
25 const fn [<cast_$orig _$dest>](orig: $orig) -> $dest {
26 let casted = orig as $dest;
28 let overflow = orig != casted as $orig;
29 if overflow { if casted == 0 { $dest::MIN } else { $dest::MAX } } else { casted }
30 }
31 }
32 };
33}
34scast![all_orig: i8, u8, i16, u16, i32, u32, i64, u64, usize, isize];
35
36macro_rules! macro_clamper {
38 ($($ip:ty, $b:literal),+) => {
39 $( macro_clamper![single: $ip, $b]; )+
40 };
41
42 (single: $ip:ty, $b:literal) => {
45 paste::paste! {
46 #[doc = "Clamps a distance to half the range of an [`" $ip "`]."]
47 pub struct [<Clamper$b>];
51
52 impl [<Clamper$b>] {
53 pub const MIN: $ip = $ip::MIN / 2;
55
56 pub const MAX: $ip = $ip::MAX / 2;
58
59 #[doc = "Clamps [`" $ip "`] distance to [`MIN`][Self::MIN]`..`[`MAX`][Self::MAX]."]
62 #[inline(always)]
68 pub const fn clamp(d: $ip) -> $ip {
69 if d < Self::MIN {
70 Self::MIN
71 } else if d > Self::MAX {
72 Self::MAX
73 } else {
74 d
75 }
76 }
77
78 #[doc = "Clamps [`" $ip "`] distance to `0..`[`MAX`][Self::MAX]."]
79 #[inline]
85 pub const fn clamp_non_negative(d: $ip) -> $ip {
86 if d < 0 {
87 0
88 } else if d > Self::MAX {
89 Self::MAX
90 } else {
91 d
92 }
93 }
94 #[doc = "Clamps [`" $ip "`] distance to `1..`[`MAX`][Self::MAX]."]
95 #[inline]
101 pub const fn clamp_positive(d: $ip) -> $ip {
102 if d < 1 {
103 1
104 } else if d > Self::MAX {
105 Self::MAX
106 } else {
107 d
108 }
109 }
110
111 #[doc = "Clamps [`i32`] distance to [`" $ip "`] [`MIN`][Self::MIN]`..`[`MAX`][Self::MAX]."]
114 #[inline(always)]
115 pub const fn clamp_from_i32(d: i32) -> $ip {
116 [<cast_i32_$ip>](d)
117 }
118 #[doc = "Clamps [`i32`] distance to [`" $ip "`] `0..`[`MAX`][Self::MAX]."]
119 #[inline(always)]
120 pub const fn clamp_non_negative_from_i32(d: i32) -> $ip {
121 if d < 0 {
122 0
123 } else {
124 [<cast_i32_$ip>](d)
125 }
126 }
127 #[doc = "Clamps [`i32`] distance to [`" $ip "`] `1..`[`MAX`][Self::MAX]."]
128 #[inline(always)]
129 pub const fn clamp_positive_from_i32(d: i32) -> $ip {
130 if d < 1 {
131 1
132 } else {
133 [<cast_i32_$ip>](d)
134 }
135 }
136
137 #[doc = "Clamps [`" $ip "`] distance to [`i32`] [`MIN`][Self::MIN]`..`[`MAX`][Self::MAX]."]
140 #[inline]
141 pub const fn clamp_to_i32(d: $ip) -> i32 {
142 if d < [<cast_i32_ $ip>](i32::MIN) {
143 i32::MIN
144 } else if d > [<cast_i32_ $ip>](i32::MAX) {
145 i32::MAX
146 } else {
147 [<cast_$ip _i32>](d)
148 }
149 }
150 #[doc = "Clamps [`" $ip "`] distance to [`i32`] `0..`[`MAX`][Self::MAX]."]
151 #[inline]
152 pub const fn clamp_non_negative_to_i32(d: $ip) -> i32 {
153 if d < 0 {
154 0
155 } else if d > [<cast_i32_ $ip>](i32::MAX) {
156 i32::MAX
157 } else {
158 [<cast_$ip _i32>](d)
159 }
160 }
161 #[doc = "Clamps [`" $ip "`] distance to [`i32`] `1..`[`MAX`][Self::MAX]."]
162 #[inline]
163 pub const fn clamp_positive_to_i32(d: $ip) -> i32 {
164 if d < 1 {
165 1
166 } else if d > [<cast_i32_ $ip>](i32::MAX) {
167 i32::MAX
168 } else {
169 [<cast_$ip _i32>](d)
170 }
171 }
172
173 #[doc = "Clamps an [`u32`] distance to [`" $ip "`] `0..`[`MAX`][Self::MAX]."]
176 #[inline]
177 pub const fn clamp_from_u32(d: u32) -> $ip {
178 if d > [<cast_$ip _u32>](Self::MAX) {
179 Self::MAX
180 } else {
181 [<cast_u32_$ip>](d)
182 }
183 }
184 #[doc = "Clamps [`u32`] distance to [`" $ip "`] `1..`[`MAX`][Self::MAX]."]
185 #[inline]
186 pub const fn clamp_positive_from_u32(d: u32) -> $ip {
187 if d == 0 {
188 1
189 } else if d > [<cast_$ip _u32>](Self::MAX) {
190 Self::MAX
191 } else {
192 [<cast_u32_$ip>](d)
193 }
194 }
195
196 #[doc = "Clamps [`" $ip "`] distance to [`u32`] `0..`[`MAX`][Self::MAX]."]
199 #[inline]
200 pub const fn clamp_to_u32(d: $ip) -> u32 {
201 [<cast _$ip _u32>](Self::clamp_non_negative(d))
202 }
203 #[doc = "Clamps [`" $ip "`] distance to [`u32`] `1..`[`MAX`][Self::MAX]."]
204 #[inline]
205 pub const fn clamp_positive_to_u32(d: $ip) -> u32 {
206 [<cast _$ip _u32>](Self::clamp_positive(d))
207 }
208
209 #[doc = "Clamps [`u16`] distance to [`" $ip "`] `0..`[`MAX`][Self::MAX]."]
212 #[inline]
213 pub const fn clamp_from_u16(d: u16) -> $ip {
214 if d > [<cast_$ip _u16>](Self::MAX) {
215 Self::MAX
216 } else {
217 [<cast_u16_$ip>](d)
218 }
219 }
220 #[doc = "Clamps [`u16`] distance to [`" $ip "`] `1..`[`MAX`][Self::MAX]."]
221 #[inline]
222 pub const fn clamp_positive_from_u16(d: u16) -> $ip {
223 if d == 0 {
224 1
225 } else if d > [<cast_$ip _u16>](Self::MAX) {
226 Self::MAX
227 } else {
228 [<cast_u16_$ip>](d)
229 }
230 }
231
232 #[doc = "Clamps [`" $ip "`] distance to [`u16`] `0..`[`MAX`][Self::MAX]."]
235 #[inline]
236 pub const fn clamp_to_u16(d: $ip) -> u16 {
237 if d < 0 {
238 0
239 } else if d > [<cast_u16_ $ip>](u16::MAX) {
240 u16::MAX
241 } else {
242 [<cast_$ip _u16>](d)
243 }
244 }
245 #[doc = "Clamps [`" $ip "`] distance to [`u16`] `1..`[`MAX`][Self::MAX]."]
246 #[inline]
247 pub const fn clamp_positive_to_u16(d: $ip) -> u16 {
248 if d < 1 {
249 1
250 } else if d > [<cast_u16_ $ip>](u16::MAX) {
251 u16::MAX
252 } else {
253 [<cast_$ip _u16>](d)
254 }
255 }
256
257 #[doc = "Clamps [`i16`] distance to [`" $ip "`] [`MIN`][Self::MIN]`..`[`MAX`][Self::MAX]."]
260 #[inline(always)]
261 pub const fn clamp_from_i16(d: i16) -> $ip {
262 [<cast_i16_$ip>](d)
263 }
264 #[doc = "Clamps [`i16`] distance to [`" $ip "`] `0..`[`MAX`][Self::MAX]."]
265 #[inline(always)]
266 pub const fn clamp_non_negative_from_i16(d: i16) -> $ip {
267 if d < 0 {
268 0
269 } else {
270 [<cast_i16_$ip>](d)
271 }
272 }
273 #[doc = "Clamps [`i16`] distance to [`" $ip "`] `1..`[`MAX`][Self::MAX]."]
274 #[inline(always)]
275 pub const fn clamp_positive_from_i16(d: i16) -> $ip {
276 if d < 1 {
277 1
278 } else {
279 [<cast_i16_$ip>](d)
280 }
281 }
282
283 #[doc = "Clamps [`" $ip "`] distance to [`i16`] [`MIN`][Self::MIN]`..`[`MAX`][Self::MAX]."]
286 #[inline]
287 pub const fn clamp_to_i16(d: $ip) -> i16 {
288 if d < [<cast_i16_ $ip>](i16::MIN) {
289 i16::MIN
290 } else if d > [<cast_i16_ $ip>](i16::MAX) {
291 i16::MAX
292 } else {
293 [<cast_$ip _i16>](d)
294 }
295 }
296 #[doc = "Clamps [`" $ip "`] distance to [`i16`] `0..`[`MAX`][Self::MAX]."]
297 #[inline]
298 pub const fn clamp_non_negative_to_i16(d: $ip) -> i16 {
299 if d < 0 {
300 0
301 } else if d > [<cast_i16_ $ip>](i16::MAX) {
302 i16::MAX
303 } else {
304 [<cast_$ip _i16>](d)
305 }
306 }
307 #[doc = "Clamps [`" $ip "`] distance to [`i16`] `1..`[`MAX`][Self::MAX]."]
308 #[inline]
309 pub const fn clamp_positive_to_i16(d: $ip) -> i16 {
310 if d < 1 {
311 1
312 } else if d > [<cast_i16_ $ip>](i16::MAX) {
313 i16::MAX
314 } else {
315 [<cast_$ip _i16>](d)
316 }
317 }
318
319 #[doc = "Clamps [`usize`] distance to [`" $ip "`] `0..`[`MAX`][Self::MAX]."]
322 #[inline]
323 pub const fn clamp_from_usize(d: usize) -> $ip {
324 if d > [<cast_$ip _usize>](Self::MAX) {
325 Self::MAX
326 } else {
327 [<cast_usize_$ip>](d)
328 }
329 }
330 #[doc = "Clamps [`usize`] distance to [`" $ip "`] `1..`[`MAX`][Self::MAX]."]
331 #[inline]
332 pub const fn clamp_positive_from_usize(d: usize) -> $ip {
333 if d == 0 {
334 1
335 } else if d > [<cast_$ip _usize>](Self::MAX) {
336 Self::MAX
337 } else {
338 [<cast_usize_$ip>](d)
339 }
340 }
341
342 #[doc = "Clamps [`" $ip "`] distance to [`usize`] `0..`[`MAX`][Self::MAX]."]
345 #[inline]
346 pub const fn clamp_to_usize(d: $ip) -> usize {
347 [<cast_$ip _usize>](Self::clamp_non_negative(d))
348 }
349 #[doc = "Clamps [`" $ip "`] distance to [`usize`] `1..`[`MAX`][Self::MAX]."]
350 #[inline]
351 pub const fn clamp_positive_to_usize(d: $ip) -> usize {
352 [<cast_$ip _usize>](Self::clamp_positive(d))
353 }
354 }
355 }
356 };
357}
358macro_clamper![i8, 8, i16, 16, i32, 32, i64, 64];