1#![cfg_attr(docs_rs, feature(doc_auto_cfg))]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![deny(
4 anonymous_parameters,
5 clippy::all,
6 clippy::missing_safety_doc,
7 clippy::missing_safety_doc,
8 clippy::undocumented_unsafe_blocks,
9 illegal_floating_point_literal_pattern,
10 late_bound_lifetime_arguments,
11 patterns_in_fns_without_body,
12 rust_2018_idioms,
13 trivial_casts,
14 trivial_numeric_casts,
15 unreachable_pub,
16 unsafe_op_in_unsafe_fn,
17 unused_extern_crates
18)]
19#![warn(
20 clippy::dbg_macro,
21 clippy::decimal_literal_representation,
22 clippy::get_unwrap,
23 clippy::nursery,
24 clippy::pedantic,
25 clippy::todo,
26 clippy::unimplemented,
27 clippy::unwrap_used,
28 clippy::use_debug,
29 missing_copy_implementations,
30 missing_debug_implementations,
31 unused_qualifications,
32 variant_size_differences
33)]
34#![allow(
35 path_statements, // used for static assertions
36 clippy::inline_always,
37 clippy::missing_errors_doc,
38 clippy::must_use_candidate,
39 clippy::redundant_pub_crate,
40)]
41#![doc(test(attr(deny(warnings))))]
42
43#[cfg(test)]
44mod tests;
45mod traits;
46mod unsafe_wrapper;
47
48#[cfg(feature = "alloc")]
49#[allow(unused_extern_crates)]
50extern crate alloc;
51
52use core::borrow::Borrow;
53use core::cmp::Ordering;
54use core::fmt;
55use core::num::IntErrorKind;
56use core::str::FromStr;
57#[cfg(feature = "std")]
58use std::error::Error;
59
60#[cfg(feature = "powerfmt")]
61use powerfmt::smart_display;
62
63use crate::unsafe_wrapper::Unsafe;
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct TryFromIntError;
67
68impl fmt::Display for TryFromIntError {
69 #[inline]
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 f.write_str(data:"out of range integral type conversion attempted")
72 }
73}
74#[cfg(feature = "std")]
75impl Error for TryFromIntError {}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct ParseIntError {
79 kind: IntErrorKind,
80}
81
82impl ParseIntError {
83 /// Outputs the detailed cause of parsing an integer failing.
84 // This function is not const because the counterpart of stdlib isn't
85 #[allow(clippy::missing_const_for_fn)]
86 #[inline(always)]
87 pub fn kind(&self) -> &IntErrorKind {
88 &self.kind
89 }
90}
91
92impl fmt::Display for ParseIntError {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 match&'static str self.kind {
95 IntErrorKind::Empty => "cannot parse integer from empty string",
96 IntErrorKind::InvalidDigit => "invalid digit found in string",
97 IntErrorKind::PosOverflow => "number too large to fit in target type",
98 IntErrorKind::NegOverflow => "number too small to fit in target type",
99 IntErrorKind::Zero => "number would be zero for non-zero type",
100 _ => "Unknown Int error kind",
101 }
102 .fmt(f)
103 }
104}
105
106#[cfg(feature = "std")]
107impl Error for ParseIntError {}
108
109macro_rules! const_try_opt {
110 ($e:expr) => {
111 match $e {
112 Some(value) => value,
113 None => return None,
114 }
115 };
116}
117
118macro_rules! if_signed {
119 (true $($x:tt)*) => { $($x)*};
120 (false $($x:tt)*) => {};
121}
122
123macro_rules! if_unsigned {
124 (true $($x:tt)*) => {};
125 (false $($x:tt)*) => { $($x)* };
126}
127
128macro_rules! article {
129 (true) => {
130 "An"
131 };
132 (false) => {
133 "A"
134 };
135}
136
137macro_rules! unsafe_unwrap_unchecked {
138 ($e:expr) => {{
139 let opt = $e;
140 debug_assert!(opt.is_some());
141 match $e {
142 Some(value) => value,
143 None => core::hint::unreachable_unchecked(),
144 }
145 }};
146}
147
148/// Informs the optimizer that a condition is always true. If the condition is false, the behavior
149/// is undefined.
150///
151/// # Safety
152///
153/// `b` must be `true`.
154#[inline]
155const unsafe fn assume(b: bool) {
156 debug_assert!(b);
157 if !b {
158 // Safety: The caller must ensure that `b` is true.
159 unsafe { core::hint::unreachable_unchecked() }
160 }
161}
162
163macro_rules! impl_ranged {
164 ($(
165 $type:ident {
166 mod_name: $mod_name:ident
167 internal: $internal:ident
168 signed: $is_signed:ident
169 unsigned: $unsigned_type:ident
170 optional: $optional_type:ident
171 }
172 )*) => {$(
173 #[doc = concat!(
174 article!($is_signed),
175 " `",
176 stringify!($internal),
177 "` that is known to be in the range `MIN..=MAX`.",
178 )]
179 #[repr(transparent)]
180 #[derive(Clone, Copy, Eq, Ord, Hash)]
181 pub struct $type<const MIN: $internal, const MAX: $internal>(
182 Unsafe<$internal>,
183 );
184
185 #[doc = concat!(
186 "A `",
187 stringify!($type),
188 "` that is optional. Equivalent to [`Option<",
189 stringify!($type),
190 ">`] with niche value optimization.",
191 )]
192 ///
193 #[doc = concat!(
194 "If `MIN` is [`",
195 stringify!($internal),
196 "::MIN`] _and_ `MAX` is [`",
197 stringify!($internal)
198 ,"::MAX`] then compilation will fail. This is because there is no way to represent \
199 the niche value.",
200 )]
201 ///
202 /// This type is useful when you need to store an optional ranged value in a struct, but
203 /// do not want the overhead of an `Option` type. This reduces the size of the struct
204 /// overall, and is particularly useful when you have a large number of optional fields.
205 /// Note that most operations must still be performed on the [`Option`] type, which is
206 #[doc = concat!("obtained with [`", stringify!($optional_type), "::get`].")]
207 #[repr(transparent)]
208 #[derive(Clone, Copy, Eq, Hash)]
209 pub struct $optional_type<const MIN: $internal, const MAX: $internal>(
210 $internal,
211 );
212
213 impl $type<0, 0> {
214 #[inline(always)]
215 pub const fn exact<const VALUE: $internal>() -> $type<VALUE, VALUE> {
216 // Safety: The value is the only one in range.
217 unsafe { $type::new_unchecked(VALUE) }
218 }
219 }
220
221 impl<const MIN: $internal, const MAX: $internal> $type<MIN, MAX> {
222 /// The smallest value that can be represented by this type.
223 // Safety: `MIN` is in range by definition.
224 pub const MIN: Self = Self::new_static::<MIN>();
225
226 /// The largest value that can be represented by this type.
227 // Safety: `MAX` is in range by definition.
228 pub const MAX: Self = Self::new_static::<MAX>();
229
230 /// Creates a ranged integer without checking the value.
231 ///
232 /// # Safety
233 ///
234 /// The value must be within the range `MIN..=MAX`.
235 #[inline(always)]
236 pub const unsafe fn new_unchecked(value: $internal) -> Self {
237 <Self as $crate::traits::RangeIsValid>::ASSERT;
238 // Safety: The caller must ensure that the value is in range.
239 unsafe {
240 $crate::assume(MIN <= value && value <= MAX);
241 Self(Unsafe::new(value))
242 }
243 }
244
245 /// Returns the value as a primitive type.
246 #[inline(always)]
247 pub const fn get(self) -> $internal {
248 <Self as $crate::traits::RangeIsValid>::ASSERT;
249 // Safety: A stored value is always in range.
250 unsafe { $crate::assume(MIN <= *self.0.get() && *self.0.get() <= MAX) };
251 *self.0.get()
252 }
253
254 #[inline(always)]
255 pub(crate) const fn get_ref(&self) -> &$internal {
256 <Self as $crate::traits::RangeIsValid>::ASSERT;
257 let value = self.0.get();
258 // Safety: A stored value is always in range.
259 unsafe { $crate::assume(MIN <= *value && *value <= MAX) };
260 value
261 }
262
263 /// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
264 #[inline(always)]
265 pub const fn new(value: $internal) -> Option<Self> {
266 <Self as $crate::traits::RangeIsValid>::ASSERT;
267 if value < MIN || value > MAX {
268 None
269 } else {
270 // Safety: The value is in range.
271 Some(unsafe { Self::new_unchecked(value) })
272 }
273 }
274
275 /// Creates a ranged integer with a statically known value. **Fails to compile** if the
276 /// value is not in range.
277 #[inline(always)]
278 pub const fn new_static<const VALUE: $internal>() -> Self {
279 <($type<MIN, VALUE>, $type<VALUE, MAX>) as $crate::traits::StaticIsValid>::ASSERT;
280 // Safety: The value is in range.
281 unsafe { Self::new_unchecked(VALUE) }
282 }
283
284 /// Creates a ranged integer with the given value, saturating if it is out of range.
285 #[inline]
286 pub const fn new_saturating(value: $internal) -> Self {
287 <Self as $crate::traits::RangeIsValid>::ASSERT;
288 if value < MIN {
289 Self::MIN
290 } else if value > MAX {
291 Self::MAX
292 } else {
293 // Safety: The value is in range.
294 unsafe { Self::new_unchecked(value) }
295 }
296 }
297
298 /// Expand the range that the value may be in. **Fails to compile** if the new range is
299 /// not a superset of the current range.
300 pub const fn expand<const NEW_MIN: $internal, const NEW_MAX: $internal>(
301 self,
302 ) -> $type<NEW_MIN, NEW_MAX> {
303 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
304 <$type<NEW_MIN, NEW_MAX> as $crate::traits::RangeIsValid>::ASSERT;
305 <($type<MIN, MAX>, $type<NEW_MIN, NEW_MAX>) as $crate::traits::ExpandIsValid>
306 ::ASSERT;
307 // Safety: The range is widened.
308 unsafe { $type::new_unchecked(self.get()) }
309 }
310
311 /// Attempt to narrow the range that the value may be in. Returns `None` if the value
312 /// is outside the new range. **Fails to compile** if the new range is not a subset of
313 /// the current range.
314 pub const fn narrow<
315 const NEW_MIN: $internal,
316 const NEW_MAX: $internal,
317 >(self) -> Option<$type<NEW_MIN, NEW_MAX>> {
318 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
319 <$type<NEW_MIN, NEW_MAX> as $crate::traits::RangeIsValid>::ASSERT;
320 <($type<MIN, MAX>, $type<NEW_MIN, NEW_MAX>) as $crate::traits::NarrowIsValid>
321 ::ASSERT;
322 $type::<NEW_MIN, NEW_MAX>::new(self.get())
323 }
324
325 /// Converts a string slice in a given base to an integer.
326 ///
327 /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
328 /// and trailing whitespace represent an error. Digits are a subset of these characters,
329 /// depending on `radix`:
330 ///
331 /// - `0-9`
332 /// - `a-z`
333 /// - `A-Z`
334 ///
335 /// # Panics
336 ///
337 /// Panics if `radix` is not in the range `2..=36`.
338 ///
339 /// # Examples
340 ///
341 /// Basic usage:
342 ///
343 /// ```rust
344 #[doc = concat!("# use deranged::", stringify!($type), ";")]
345 #[doc = concat!(
346 "assert_eq!(",
347 stringify!($type),
348 "::<5, 10>::from_str_radix(\"A\", 16), Ok(",
349 stringify!($type),
350 "::new_static::<10>()));",
351 )]
352 /// ```
353 #[inline]
354 pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
355 <Self as $crate::traits::RangeIsValid>::ASSERT;
356 match $internal::from_str_radix(src, radix) {
357 Ok(value) if value > MAX => {
358 Err(ParseIntError { kind: IntErrorKind::PosOverflow })
359 }
360 Ok(value) if value < MIN => {
361 Err(ParseIntError { kind: IntErrorKind::NegOverflow })
362 }
363 // Safety: If the value was out of range, it would have been caught in a
364 // previous arm.
365 Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
366 Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
367 }
368 }
369
370 /// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
371 /// value is out of range.
372 #[must_use = "this returns the result of the operation, without modifying the original"]
373 #[inline]
374 pub const fn checked_add(self, rhs: $internal) -> Option<Self> {
375 <Self as $crate::traits::RangeIsValid>::ASSERT;
376 Self::new(const_try_opt!(self.get().checked_add(rhs)))
377 }
378
379 /// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
380 /// range.
381 ///
382 /// # Safety
383 ///
384 /// The result of `self + rhs` must be in the range `MIN..=MAX`.
385 #[must_use = "this returns the result of the operation, without modifying the original"]
386 #[inline(always)]
387 pub const unsafe fn unchecked_add(self, rhs: $internal) -> Self {
388 <Self as $crate::traits::RangeIsValid>::ASSERT;
389 // Safety: The caller must ensure that the result is in range.
390 unsafe {
391 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_add(rhs)))
392 }
393 }
394
395 /// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
396 /// value is out of range.
397 #[must_use = "this returns the result of the operation, without modifying the original"]
398 #[inline]
399 pub const fn checked_sub(self, rhs: $internal) -> Option<Self> {
400 <Self as $crate::traits::RangeIsValid>::ASSERT;
401 Self::new(const_try_opt!(self.get().checked_sub(rhs)))
402 }
403
404 /// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
405 /// range.
406 ///
407 /// # Safety
408 ///
409 /// The result of `self - rhs` must be in the range `MIN..=MAX`.
410 #[must_use = "this returns the result of the operation, without modifying the original"]
411 #[inline(always)]
412 pub const unsafe fn unchecked_sub(self, rhs: $internal) -> Self {
413 <Self as $crate::traits::RangeIsValid>::ASSERT;
414 // Safety: The caller must ensure that the result is in range.
415 unsafe {
416 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_sub(rhs)))
417 }
418 }
419
420 /// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
421 /// value is out of range.
422 #[must_use = "this returns the result of the operation, without modifying the original"]
423 #[inline]
424 pub const fn checked_mul(self, rhs: $internal) -> Option<Self> {
425 <Self as $crate::traits::RangeIsValid>::ASSERT;
426 Self::new(const_try_opt!(self.get().checked_mul(rhs)))
427 }
428
429 /// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
430 /// in range.
431 ///
432 /// # Safety
433 ///
434 /// The result of `self * rhs` must be in the range `MIN..=MAX`.
435 #[must_use = "this returns the result of the operation, without modifying the original"]
436 #[inline(always)]
437 pub const unsafe fn unchecked_mul(self, rhs: $internal) -> Self {
438 <Self as $crate::traits::RangeIsValid>::ASSERT;
439 // Safety: The caller must ensure that the result is in range.
440 unsafe {
441 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_mul(rhs)))
442 }
443 }
444
445 /// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
446 /// if the resulting value is out of range.
447 #[must_use = "this returns the result of the operation, without modifying the original"]
448 #[inline]
449 pub const fn checked_div(self, rhs: $internal) -> Option<Self> {
450 <Self as $crate::traits::RangeIsValid>::ASSERT;
451 Self::new(const_try_opt!(self.get().checked_div(rhs)))
452 }
453
454 /// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
455 /// the result is in range.
456 ///
457 /// # Safety
458 ///
459 /// `self` must not be zero and the result of `self / rhs` must be in the range
460 /// `MIN..=MAX`.
461 #[must_use = "this returns the result of the operation, without modifying the original"]
462 #[inline(always)]
463 pub const unsafe fn unchecked_div(self, rhs: $internal) -> Self {
464 <Self as $crate::traits::RangeIsValid>::ASSERT;
465 // Safety: The caller must ensure that the result is in range and that `rhs` is not
466 // zero.
467 unsafe {
468 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_div(rhs)))
469 }
470 }
471
472 /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
473 /// `rhs == 0` or if the resulting value is out of range.
474 #[must_use = "this returns the result of the operation, without modifying the original"]
475 #[inline]
476 pub const fn checked_div_euclid(self, rhs: $internal) -> Option<Self> {
477 <Self as $crate::traits::RangeIsValid>::ASSERT;
478 Self::new(const_try_opt!(self.get().checked_div_euclid(rhs)))
479 }
480
481 /// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
482 /// `rhs != 0` and that the result is in range.
483 ///
484 /// # Safety
485 ///
486 /// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
487 /// range `MIN..=MAX`.
488 #[must_use = "this returns the result of the operation, without modifying the original"]
489 #[inline(always)]
490 pub const unsafe fn unchecked_div_euclid(self, rhs: $internal) -> Self {
491 <Self as $crate::traits::RangeIsValid>::ASSERT;
492 // Safety: The caller must ensure that the result is in range and that `rhs` is not
493 // zero.
494 unsafe {
495 Self::new_unchecked(
496 unsafe_unwrap_unchecked!(self.get().checked_div_euclid(rhs))
497 )
498 }
499 }
500
501 if_unsigned!($is_signed
502 /// Remainder. Computes `self % rhs`, statically guaranteeing that the returned value
503 /// is in range.
504 #[must_use = "this returns the result of the operation, without modifying the original"]
505 #[inline]
506 pub const fn rem<const RHS_VALUE: $internal>(
507 self,
508 rhs: $type<RHS_VALUE, RHS_VALUE>,
509 ) -> $type<0, RHS_VALUE> {
510 <Self as $crate::traits::RangeIsValid>::ASSERT;
511 // Safety: The result is guaranteed to be in range due to the nature of remainder on
512 // unsigned integers.
513 unsafe { $type::new_unchecked(self.get() % rhs.get()) }
514 });
515
516 /// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
517 /// if the resulting value is out of range.
518 #[must_use = "this returns the result of the operation, without modifying the original"]
519 #[inline]
520 pub const fn checked_rem(self, rhs: $internal) -> Option<Self> {
521 <Self as $crate::traits::RangeIsValid>::ASSERT;
522 Self::new(const_try_opt!(self.get().checked_rem(rhs)))
523 }
524
525 /// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
526 /// result is in range.
527 ///
528 /// # Safety
529 ///
530 /// `self` must not be zero and the result of `self % rhs` must be in the range
531 /// `MIN..=MAX`.
532 #[must_use = "this returns the result of the operation, without modifying the original"]
533 #[inline(always)]
534 pub const unsafe fn unchecked_rem(self, rhs: $internal) -> Self {
535 <Self as $crate::traits::RangeIsValid>::ASSERT;
536 // Safety: The caller must ensure that the result is in range and that `rhs` is not
537 // zero.
538 unsafe {
539 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_rem(rhs)))
540 }
541 }
542
543 /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
544 /// `rhs == 0` or if the resulting value is out of range.
545 #[must_use = "this returns the result of the operation, without modifying the original"]
546 #[inline]
547 pub const fn checked_rem_euclid(self, rhs: $internal) -> Option<Self> {
548 <Self as $crate::traits::RangeIsValid>::ASSERT;
549 Self::new(const_try_opt!(self.get().checked_rem_euclid(rhs)))
550 }
551
552 /// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
553 /// `rhs != 0` and that the result is in range.
554 ///
555 /// # Safety
556 ///
557 /// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
558 /// range `MIN..=MAX`.
559 #[must_use = "this returns the result of the operation, without modifying the original"]
560 #[inline(always)]
561 pub const unsafe fn unchecked_rem_euclid(self, rhs: $internal) -> Self {
562 <Self as $crate::traits::RangeIsValid>::ASSERT;
563 // Safety: The caller must ensure that the result is in range and that `rhs` is not
564 // zero.
565 unsafe {
566 Self::new_unchecked(
567 unsafe_unwrap_unchecked!(self.get().checked_rem_euclid(rhs))
568 )
569 }
570 }
571
572 /// Checked negation. Computes `-self`, returning `None` if the resulting value is out
573 /// of range.
574 #[must_use = "this returns the result of the operation, without modifying the original"]
575 #[inline]
576 pub const fn checked_neg(self) -> Option<Self> {
577 <Self as $crate::traits::RangeIsValid>::ASSERT;
578 Self::new(const_try_opt!(self.get().checked_neg()))
579 }
580
581 /// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
582 ///
583 /// # Safety
584 ///
585 /// The result of `-self` must be in the range `MIN..=MAX`.
586 #[must_use = "this returns the result of the operation, without modifying the original"]
587 #[inline(always)]
588 pub const unsafe fn unchecked_neg(self) -> Self {
589 <Self as $crate::traits::RangeIsValid>::ASSERT;
590 // Safety: The caller must ensure that the result is in range.
591 unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_neg())) }
592 }
593
594 /// Negation. Computes `self.neg()`, **failing to compile** if the result is not
595 /// guaranteed to be in range.
596 #[must_use = "this returns the result of the operation, without modifying the original"]
597 #[inline(always)]
598 pub const fn neg(self) -> Self {
599 <Self as $crate::traits::RangeIsValid>::ASSERT;
600 <Self as $crate::traits::NegIsSafe>::ASSERT;
601 // Safety: The compiler asserts that the result is in range.
602 unsafe { self.unchecked_neg() }
603 }
604
605 /// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
606 /// is out of range.
607 #[must_use = "this returns the result of the operation, without modifying the original"]
608 #[inline]
609 pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
610 <Self as $crate::traits::RangeIsValid>::ASSERT;
611 Self::new(const_try_opt!(self.get().checked_shl(rhs)))
612 }
613
614 /// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
615 ///
616 /// # Safety
617 ///
618 /// The result of `self << rhs` must be in the range `MIN..=MAX`.
619 #[must_use = "this returns the result of the operation, without modifying the original"]
620 #[inline(always)]
621 pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
622 <Self as $crate::traits::RangeIsValid>::ASSERT;
623 // Safety: The caller must ensure that the result is in range.
624 unsafe {
625 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shl(rhs)))
626 }
627 }
628
629 /// Checked shift right. Computes `self >> rhs`, returning `None` if
630 /// the resulting value is out of range.
631 #[must_use = "this returns the result of the operation, without modifying the original"]
632 #[inline]
633 pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
634 <Self as $crate::traits::RangeIsValid>::ASSERT;
635 Self::new(const_try_opt!(self.get().checked_shr(rhs)))
636 }
637
638 /// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
639 ///
640 /// # Safety
641 ///
642 /// The result of `self >> rhs` must be in the range `MIN..=MAX`.
643 #[must_use = "this returns the result of the operation, without modifying the original"]
644 #[inline(always)]
645 pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
646 <Self as $crate::traits::RangeIsValid>::ASSERT;
647 // Safety: The caller must ensure that the result is in range.
648 unsafe {
649 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shr(rhs)))
650 }
651 }
652
653 if_signed!($is_signed
654 /// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
655 /// value is out of range.
656 #[must_use = "this returns the result of the operation, without modifying the original"]
657 #[inline]
658 pub const fn checked_abs(self) -> Option<Self> {
659 <Self as $crate::traits::RangeIsValid>::ASSERT;
660 Self::new(const_try_opt!(self.get().checked_abs()))
661 }
662
663 /// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
664 /// range.
665 ///
666 /// # Safety
667 ///
668 /// The result of `self.abs()` must be in the range `MIN..=MAX`.
669 #[must_use = "this returns the result of the operation, without modifying the original"]
670 #[inline(always)]
671 pub const unsafe fn unchecked_abs(self) -> Self {
672 <Self as $crate::traits::RangeIsValid>::ASSERT;
673 // Safety: The caller must ensure that the result is in range.
674 unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_abs())) }
675 }
676
677 /// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
678 /// guaranteed to be in range.
679 #[must_use = "this returns the result of the operation, without modifying the original"]
680 #[inline(always)]
681 pub const fn abs(self) -> Self {
682 <Self as $crate::traits::RangeIsValid>::ASSERT;
683 <Self as $crate::traits::AbsIsSafe>::ASSERT;
684 // Safety: The compiler asserts that the result is in range.
685 unsafe { self.unchecked_abs() }
686 });
687
688 /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
689 /// value is out of range.
690 #[must_use = "this returns the result of the operation, without modifying the original"]
691 #[inline]
692 pub const fn checked_pow(self, exp: u32) -> Option<Self> {
693 <Self as $crate::traits::RangeIsValid>::ASSERT;
694 Self::new(const_try_opt!(self.get().checked_pow(exp)))
695 }
696
697 /// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
698 /// range.
699 ///
700 /// # Safety
701 ///
702 /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
703 #[must_use = "this returns the result of the operation, without modifying the original"]
704 #[inline(always)]
705 pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
706 <Self as $crate::traits::RangeIsValid>::ASSERT;
707 // Safety: The caller must ensure that the result is in range.
708 unsafe {
709 Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_pow(exp)))
710 }
711 }
712
713 /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
714 /// bounds.
715 #[must_use = "this returns the result of the operation, without modifying the original"]
716 #[inline]
717 pub const fn saturating_add(self, rhs: $internal) -> Self {
718 <Self as $crate::traits::RangeIsValid>::ASSERT;
719 Self::new_saturating(self.get().saturating_add(rhs))
720 }
721
722 /// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
723 /// bounds.
724 #[must_use = "this returns the result of the operation, without modifying the original"]
725 #[inline]
726 pub const fn saturating_sub(self, rhs: $internal) -> Self {
727 <Self as $crate::traits::RangeIsValid>::ASSERT;
728 Self::new_saturating(self.get().saturating_sub(rhs))
729 }
730
731 if_signed!($is_signed
732 /// Saturating integer negation. Computes `self - rhs`, saturating at the numeric
733 /// bounds.
734 #[must_use = "this returns the result of the operation, without modifying the original"]
735 #[inline]
736 pub const fn saturating_neg(self) -> Self {
737 <Self as $crate::traits::RangeIsValid>::ASSERT;
738 Self::new_saturating(self.get().saturating_neg())
739 });
740
741 if_signed!($is_signed
742 /// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
743 #[must_use = "this returns the result of the operation, without modifying the original"]
744 #[inline]
745 pub const fn saturating_abs(self) -> Self {
746 <Self as $crate::traits::RangeIsValid>::ASSERT;
747 Self::new_saturating(self.get().saturating_abs())
748 });
749
750 /// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
751 /// bounds.
752 #[must_use = "this returns the result of the operation, without modifying the original"]
753 #[inline]
754 pub const fn saturating_mul(self, rhs: $internal) -> Self {
755 <Self as $crate::traits::RangeIsValid>::ASSERT;
756 Self::new_saturating(self.get().saturating_mul(rhs))
757 }
758
759 /// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
760 /// numeric bounds.
761 #[must_use = "this returns the result of the operation, without modifying the original"]
762 #[inline]
763 pub const fn saturating_pow(self, exp: u32) -> Self {
764 <Self as $crate::traits::RangeIsValid>::ASSERT;
765 Self::new_saturating(self.get().saturating_pow(exp))
766 }
767
768 /// Compute the `rem_euclid` of this type with its unsigned type equivalent
769 // Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
770 // Also because this isn't implemented for normal types in std.
771 // TODO maybe make public anyway? It is useful.
772 #[must_use = "this returns the result of the operation, without modifying the original"]
773 #[inline]
774 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
775 const fn rem_euclid_unsigned(
776 rhs: $internal,
777 range_len: $unsigned_type
778 ) -> $unsigned_type {
779 #[allow(unused_comparisons)]
780 if rhs >= 0 {
781 (rhs as $unsigned_type) % range_len
782 } else {
783 // Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
784 // Can't write -ux or ux::abs() method. This gets around compilation error.
785 // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
786 let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
787 // Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
788 // Also = 0 in mod range_len arithmetic.
789 // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
790 // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
791 // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
792 // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
793 ((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
794 }
795 }
796
797 /// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
798 /// bounds.
799 #[must_use = "this returns the result of the operation, without modifying the original"]
800 #[inline]
801 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
802 pub const fn wrapping_add(self, rhs: $internal) -> Self {
803 <Self as $crate::traits::RangeIsValid>::ASSERT;
804 // Forward to internal type's impl if same as type.
805 if MIN == $internal::MIN && MAX == $internal::MAX {
806 // Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
807 return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
808 }
809
810 let inner = self.get();
811
812 // Won't overflow because of std impl forwarding.
813 let range_len = MAX.abs_diff(MIN) + 1;
814
815 // Calculate the offset with proper handling for negative rhs
816 let offset = Self::rem_euclid_unsigned(rhs, range_len);
817
818 let greater_vals = MAX.abs_diff(inner);
819 // No wrap
820 if offset <= greater_vals {
821 // Safety:
822 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
823 // if inner < 0: Same as >=0 with caveat:
824 // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
825 // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
826 // (the difference doesn't matter since it won't overflow),
827 // but unsigned integers don't have either method so it won't compile that way.
828 unsafe { Self::new_unchecked(
829 ((inner as $unsigned_type).wrapping_add(offset)) as $internal
830 ) }
831 }
832 // Wrap
833 else {
834 // Safety:
835 // - offset < range_len by rem_euclid (MIN + ... safe)
836 // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
837 //
838 // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
839 unsafe { Self::new_unchecked(
840 ((MIN as $unsigned_type).wrapping_add(
841 offset - (greater_vals + 1)
842 )) as $internal
843 ) }
844 }
845 }
846
847 /// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
848 /// bounds.
849 #[must_use = "this returns the result of the operation, without modifying the original"]
850 #[inline]
851 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
852 pub const fn wrapping_sub(self, rhs: $internal) -> Self {
853 <Self as $crate::traits::RangeIsValid>::ASSERT;
854 // Forward to internal type's impl if same as type.
855 if MIN == $internal::MIN && MAX == $internal::MAX {
856 // Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
857 return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
858 }
859
860 let inner = self.get();
861
862 // Won't overflow because of std impl forwarding.
863 let range_len = MAX.abs_diff(MIN) + 1;
864
865 // Calculate the offset with proper handling for negative rhs
866 let offset = Self::rem_euclid_unsigned(rhs, range_len);
867
868 let lesser_vals = MIN.abs_diff(inner);
869 // No wrap
870 if offset <= lesser_vals {
871 // Safety:
872 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
873 // if inner < 0: Same as >=0 with caveat:
874 // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
875 // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
876 // (the difference doesn't matter since it won't overflow below 0),
877 // but unsigned integers don't have either method so it won't compile that way.
878 unsafe { Self::new_unchecked(
879 ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
880 ) }
881 }
882 // Wrap
883 else {
884 // Safety:
885 // - offset < range_len by rem_euclid (MAX - ... safe)
886 // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
887 //
888 // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
889 unsafe { Self::new_unchecked(
890 ((MAX as $unsigned_type).wrapping_sub(
891 offset - (lesser_vals + 1)
892 )) as $internal
893 ) }
894 }
895 }
896 }
897
898 impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
899 /// The value used as the niche. Must not be in the range `MIN..=MAX`.
900 const NICHE: $internal = match (MIN, MAX) {
901 ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
902 ($internal::MIN, _) => $internal::MAX,
903 (_, _) => $internal::MIN,
904 };
905
906 /// An optional ranged value that is not present.
907 #[allow(non_upper_case_globals)]
908 pub const None: Self = Self(Self::NICHE);
909
910 /// Creates an optional ranged value that is present.
911 #[allow(non_snake_case)]
912 #[inline(always)]
913 pub const fn Some(value: $type<MIN, MAX>) -> Self {
914 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
915 Self(value.get())
916 }
917
918 /// Returns the value as the standard library's [`Option`] type.
919 #[inline(always)]
920 pub const fn get(self) -> Option<$type<MIN, MAX>> {
921 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
922 if self.0 == Self::NICHE {
923 None
924 } else {
925 // Safety: A stored value that is not the niche is always in range.
926 Some(unsafe { $type::new_unchecked(self.0) })
927 }
928 }
929
930 /// Creates an optional ranged integer without checking the value.
931 ///
932 /// # Safety
933 ///
934 /// The value must be within the range `MIN..=MAX`. As the value used for niche
935 /// value optimization is unspecified, the provided value must not be the niche
936 /// value.
937 #[inline(always)]
938 pub const unsafe fn some_unchecked(value: $internal) -> Self {
939 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
940 // Safety: The caller must ensure that the value is in range.
941 unsafe { $crate::assume(MIN <= value && value <= MAX) };
942 Self(value)
943 }
944
945 /// Obtain the inner value of the struct. This is useful for comparisons.
946 #[inline(always)]
947 pub(crate) const fn inner(self) -> $internal {
948 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
949 self.0
950 }
951
952 #[inline(always)]
953 pub const fn get_primitive(self) -> Option<$internal> {
954 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
955 Some(const_try_opt!(self.get()).get())
956 }
957
958 /// Returns `true` if the value is the niche value.
959 #[inline(always)]
960 pub const fn is_none(self) -> bool {
961 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
962 self.get().is_none()
963 }
964
965 /// Returns `true` if the value is not the niche value.
966 #[inline(always)]
967 pub const fn is_some(self) -> bool {
968 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
969 self.get().is_some()
970 }
971 }
972
973 impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
974 #[inline(always)]
975 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
976 <Self as $crate::traits::RangeIsValid>::ASSERT;
977 self.get().fmt(f)
978 }
979 }
980
981 impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
982 #[inline(always)]
983 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
984 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
985 self.get().fmt(f)
986 }
987 }
988
989 impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
990 #[inline(always)]
991 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
992 <Self as $crate::traits::RangeIsValid>::ASSERT;
993 self.get().fmt(f)
994 }
995 }
996
997 #[cfg(feature = "powerfmt")]
998 impl<
999 const MIN: $internal,
1000 const MAX: $internal,
1001 > smart_display::SmartDisplay for $type<MIN, MAX> {
1002 type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
1003
1004 #[inline(always)]
1005 fn metadata(
1006 &self,
1007 f: smart_display::FormatterOptions,
1008 ) -> smart_display::Metadata<'_, Self> {
1009 <Self as $crate::traits::RangeIsValid>::ASSERT;
1010 self.get_ref().metadata(f).reuse()
1011 }
1012
1013 #[inline(always)]
1014 fn fmt_with_metadata(
1015 &self,
1016 f: &mut fmt::Formatter<'_>,
1017 metadata: smart_display::Metadata<'_, Self>,
1018 ) -> fmt::Result {
1019 <Self as $crate::traits::RangeIsValid>::ASSERT;
1020 self.get().fmt_with_metadata(f, metadata.reuse())
1021 }
1022 }
1023
1024 impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
1025 #[inline(always)]
1026 fn default() -> Self {
1027 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1028 Self::None
1029 }
1030 }
1031
1032 impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
1033 #[inline(always)]
1034 fn as_ref(&self) -> &$internal {
1035 <Self as $crate::traits::RangeIsValid>::ASSERT;
1036 &self.get_ref()
1037 }
1038 }
1039
1040 impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
1041 #[inline(always)]
1042 fn borrow(&self) -> &$internal {
1043 <Self as $crate::traits::RangeIsValid>::ASSERT;
1044 &self.get_ref()
1045 }
1046 }
1047
1048 impl<
1049 const MIN_A: $internal,
1050 const MAX_A: $internal,
1051 const MIN_B: $internal,
1052 const MAX_B: $internal,
1053 > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1054 #[inline(always)]
1055 fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
1056 <Self as $crate::traits::RangeIsValid>::ASSERT;
1057 <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
1058 self.get() == other.get()
1059 }
1060 }
1061
1062 impl<
1063 const MIN_A: $internal,
1064 const MAX_A: $internal,
1065 const MIN_B: $internal,
1066 const MAX_B: $internal,
1067 > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1068 #[inline(always)]
1069 fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
1070 <$type<MIN_A, MAX_A> as $crate::traits::RangeIsValid>::ASSERT;
1071 <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
1072 self.inner() == other.inner()
1073 }
1074 }
1075
1076 impl<
1077 const MIN_A: $internal,
1078 const MAX_A: $internal,
1079 const MIN_B: $internal,
1080 const MAX_B: $internal,
1081 > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1082 #[inline(always)]
1083 fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
1084 <Self as $crate::traits::RangeIsValid>::ASSERT;
1085 <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
1086 self.get().partial_cmp(&other.get())
1087 }
1088 }
1089
1090 impl<
1091 const MIN_A: $internal,
1092 const MAX_A: $internal,
1093 const MIN_B: $internal,
1094 const MAX_B: $internal,
1095 > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1096 #[inline]
1097 fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
1098 <$type<MIN_A, MAX_A> as $crate::traits::RangeIsValid>::ASSERT;
1099 <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
1100 if self.is_none() && other.is_none() {
1101 Some(Ordering::Equal)
1102 } else if self.is_none() {
1103 Some(Ordering::Less)
1104 } else if other.is_none() {
1105 Some(Ordering::Greater)
1106 } else {
1107 self.inner().partial_cmp(&other.inner())
1108 }
1109 }
1110 }
1111
1112 impl<
1113 const MIN: $internal,
1114 const MAX: $internal,
1115 > Ord for $optional_type<MIN, MAX> {
1116 #[inline]
1117 fn cmp(&self, other: &Self) -> Ordering {
1118 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1119 if self.is_none() && other.is_none() {
1120 Ordering::Equal
1121 } else if self.is_none() {
1122 Ordering::Less
1123 } else if other.is_none() {
1124 Ordering::Greater
1125 } else {
1126 self.inner().cmp(&other.inner())
1127 }
1128 }
1129 }
1130
1131 impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
1132 #[inline(always)]
1133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1134 <Self as $crate::traits::RangeIsValid>::ASSERT;
1135 self.get().fmt(f)
1136 }
1137 }
1138
1139 impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
1140 #[inline(always)]
1141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 <Self as $crate::traits::RangeIsValid>::ASSERT;
1143 self.get().fmt(f)
1144 }
1145 }
1146
1147 impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
1148 #[inline(always)]
1149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1150 <Self as $crate::traits::RangeIsValid>::ASSERT;
1151 self.get().fmt(f)
1152 }
1153 }
1154
1155 impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
1156 #[inline(always)]
1157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1158 <Self as $crate::traits::RangeIsValid>::ASSERT;
1159 self.get().fmt(f)
1160 }
1161 }
1162
1163 impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
1164 #[inline(always)]
1165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1166 <Self as $crate::traits::RangeIsValid>::ASSERT;
1167 self.get().fmt(f)
1168 }
1169 }
1170
1171 impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
1172 #[inline(always)]
1173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1174 <Self as $crate::traits::RangeIsValid>::ASSERT;
1175 self.get().fmt(f)
1176 }
1177 }
1178
1179 impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
1180 #[inline(always)]
1181 fn from(value: $type<MIN, MAX>) -> Self {
1182 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1183 value.get()
1184 }
1185 }
1186
1187 impl<
1188 const MIN: $internal,
1189 const MAX: $internal,
1190 > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
1191 #[inline(always)]
1192 fn from(value: $type<MIN, MAX>) -> Self {
1193 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1194 Self::Some(value)
1195 }
1196 }
1197
1198 impl<
1199 const MIN: $internal,
1200 const MAX: $internal,
1201 > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
1202 #[inline(always)]
1203 fn from(value: Option<$type<MIN, MAX>>) -> Self {
1204 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1205 match value {
1206 Some(value) => Self::Some(value),
1207 None => Self::None,
1208 }
1209 }
1210 }
1211
1212 impl<
1213 const MIN: $internal,
1214 const MAX: $internal,
1215 > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
1216 #[inline(always)]
1217 fn from(value: $optional_type<MIN, MAX>) -> Self {
1218 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1219 value.get()
1220 }
1221 }
1222
1223 impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
1224 type Error = TryFromIntError;
1225
1226 #[inline]
1227 fn try_from(value: $internal) -> Result<Self, Self::Error> {
1228 <Self as $crate::traits::RangeIsValid>::ASSERT;
1229 Self::new(value).ok_or(TryFromIntError)
1230 }
1231 }
1232
1233 impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
1234 type Err = ParseIntError;
1235
1236 #[inline]
1237 fn from_str(s: &str) -> Result<Self, Self::Err> {
1238 <Self as $crate::traits::RangeIsValid>::ASSERT;
1239 let value = s.parse::<$internal>().map_err(|e| ParseIntError {
1240 kind: e.kind().clone()
1241 })?;
1242 if value < MIN {
1243 Err(ParseIntError { kind: IntErrorKind::NegOverflow })
1244 } else if value > MAX {
1245 Err(ParseIntError { kind: IntErrorKind::PosOverflow })
1246 } else {
1247 // Safety: The value was previously checked for validity.
1248 Ok(unsafe { Self::new_unchecked(value) })
1249 }
1250 }
1251 }
1252
1253 #[cfg(feature = "serde")]
1254 impl<const MIN: $internal, const MAX: $internal> serde::Serialize for $type<MIN, MAX> {
1255 #[inline(always)]
1256 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1257 <Self as $crate::traits::RangeIsValid>::ASSERT;
1258 self.get().serialize(serializer)
1259 }
1260 }
1261
1262 #[cfg(feature = "serde")]
1263 impl<
1264 const MIN: $internal,
1265 const MAX: $internal,
1266 > serde::Serialize for $optional_type<MIN, MAX> {
1267 #[inline(always)]
1268 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1269 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1270 self.get().serialize(serializer)
1271 }
1272 }
1273
1274 #[cfg(feature = "serde")]
1275 impl<
1276 'de,
1277 const MIN: $internal,
1278 const MAX: $internal,
1279 > serde::Deserialize<'de> for $type<MIN, MAX> {
1280 #[inline]
1281 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1282 <Self as $crate::traits::RangeIsValid>::ASSERT;
1283 let internal = <$internal>::deserialize(deserializer)?;
1284 Self::new(internal).ok_or_else(|| <D::Error as serde::de::Error>::invalid_value(
1285 serde::de::Unexpected::Other("integer"),
1286 #[cfg(feature = "std")] {
1287 &format!("an integer in the range {}..={}", MIN, MAX).as_ref()
1288 },
1289 #[cfg(not(feature = "std"))] {
1290 &"an integer in the valid range"
1291 }
1292 ))
1293 }
1294 }
1295
1296 #[cfg(feature = "serde")]
1297 impl<
1298 'de,
1299 const MIN: $internal,
1300 const MAX: $internal,
1301 > serde::Deserialize<'de> for $optional_type<MIN, MAX> {
1302 #[inline]
1303 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1304 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1305 Ok(Self::Some($type::<MIN, MAX>::deserialize(deserializer)?))
1306 }
1307 }
1308
1309 #[cfg(feature = "rand")]
1310 impl<
1311 const MIN: $internal,
1312 const MAX: $internal,
1313 > rand::distributions::Distribution<$type<MIN, MAX>> for rand::distributions::Standard {
1314 #[inline]
1315 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1316 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1317 $type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1318 }
1319 }
1320
1321 #[cfg(feature = "rand")]
1322 impl<
1323 const MIN: $internal,
1324 const MAX: $internal,
1325 > rand::distributions::Distribution<$optional_type<MIN, MAX>>
1326 for rand::distributions::Standard {
1327 #[inline]
1328 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1329 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1330 rng.gen::<Option<$type<MIN, MAX>>>().into()
1331 }
1332 }
1333
1334 #[cfg(feature = "num")]
1335 impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
1336 #[inline(always)]
1337 fn min_value() -> Self {
1338 <Self as $crate::traits::RangeIsValid>::ASSERT;
1339 Self::MIN
1340 }
1341
1342 #[inline(always)]
1343 fn max_value() -> Self {
1344 <Self as $crate::traits::RangeIsValid>::ASSERT;
1345 Self::MAX
1346 }
1347 }
1348
1349 #[cfg(feature = "quickcheck")]
1350 impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
1351 #[inline]
1352 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1353 <Self as $crate::traits::RangeIsValid>::ASSERT;
1354 // Safety: The `rem_euclid` call and addition ensure that the value is in range.
1355 unsafe {
1356 Self::new_unchecked($internal::arbitrary(g).rem_euclid(MAX - MIN + 1) + MIN)
1357 }
1358 }
1359
1360 #[inline]
1361 fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1362 ::alloc::boxed::Box::new(
1363 self.get()
1364 .shrink()
1365 .filter_map(Self::new)
1366 )
1367 }
1368 }
1369
1370 #[cfg(feature = "quickcheck")]
1371 impl<
1372 const MIN: $internal,
1373 const MAX: $internal,
1374 > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
1375 #[inline]
1376 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1377 <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
1378 Option::<$type<MIN, MAX>>::arbitrary(g).into()
1379 }
1380
1381 #[inline]
1382 fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1383 ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
1384 }
1385 }
1386 )*};
1387}
1388
1389impl_ranged! {
1390 RangedU8 {
1391 mod_name: ranged_u8
1392 internal: u8
1393 signed: false
1394 unsigned: u8
1395 optional: OptionRangedU8
1396 }
1397 RangedU16 {
1398 mod_name: ranged_u16
1399 internal: u16
1400 signed: false
1401 unsigned: u16
1402 optional: OptionRangedU16
1403 }
1404 RangedU32 {
1405 mod_name: ranged_u32
1406 internal: u32
1407 signed: false
1408 unsigned: u32
1409 optional: OptionRangedU32
1410 }
1411 RangedU64 {
1412 mod_name: ranged_u64
1413 internal: u64
1414 signed: false
1415 unsigned: u64
1416 optional: OptionRangedU64
1417 }
1418 RangedU128 {
1419 mod_name: ranged_u128
1420 internal: u128
1421 signed: false
1422 unsigned: u128
1423 optional: OptionRangedU128
1424 }
1425 RangedUsize {
1426 mod_name: ranged_usize
1427 internal: usize
1428 signed: false
1429 unsigned: usize
1430 optional: OptionRangedUsize
1431 }
1432 RangedI8 {
1433 mod_name: ranged_i8
1434 internal: i8
1435 signed: true
1436 unsigned: u8
1437 optional: OptionRangedI8
1438 }
1439 RangedI16 {
1440 mod_name: ranged_i16
1441 internal: i16
1442 signed: true
1443 unsigned: u16
1444 optional: OptionRangedI16
1445 }
1446 RangedI32 {
1447 mod_name: ranged_i32
1448 internal: i32
1449 signed: true
1450 unsigned: u32
1451 optional: OptionRangedI32
1452 }
1453 RangedI64 {
1454 mod_name: ranged_i64
1455 internal: i64
1456 signed: true
1457 unsigned: u64
1458 optional: OptionRangedI64
1459 }
1460 RangedI128 {
1461 mod_name: ranged_i128
1462 internal: i128
1463 signed: true
1464 unsigned: u128
1465 optional: OptionRangedI128
1466 }
1467 RangedIsize {
1468 mod_name: ranged_isize
1469 internal: isize
1470 signed: true
1471 unsigned: usize
1472 optional: OptionRangedIsize
1473 }
1474}
1475