1//! `deranged` is a proof-of-concept implementation of ranged integers.
23#![cfg_attr(docsrs, feature(doc_cfg))]
4#![no_std]
5#![doc(test(attr(deny(warnings))))]
67#[cfg(all(feature = "alloc", any(feature = "serde", feature = "quickcheck")))]
8extern crate alloc;
910#[cfg(test)]
11mod tests;
12mod unsafe_wrapper;
1314use core::borrow::Borrow;
15use core::cmp::Ordering;
16use core::error::Error;
17use core::fmt;
18use core::hint::assert_unchecked;
19use core::num::{IntErrorKind, NonZero};
20use core::str::FromStr;
2122/// A macro to define a ranged integer with an automatically computed inner type.
23///
24/// The minimum and maximum values are provided as integer literals, and the macro will compute an
25/// appropriate inner type to represent the range. This will be the smallest integer type that can
26/// store both the minimum and maximum values, with a preference for unsigned types if both are
27/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
28/// to either or both of the minimum and maximum values, respectively.
29///
30/// # Examples
31///
32/// ```rust,ignore
33/// int!(0, 100); // RangedU8<0, 100>
34/// int!(0i, 100); // RangedI8<0, 100>
35/// int!(-5, 5); // RangedI8<-5, 5>
36/// int!(-5u, 5); // compile error (-5 cannot be unsigned)
37/// ```
38#[cfg(all(docsrs, feature = "macros"))]
39#[macro_export]
40macro_rules! int {
41 ($min:literal, $max:literal) => {};
42}
4344/// A macro to define an optional ranged integer with an automatically computed inner type.
45///
46/// The minimum and maximum values are provided as integer literals, and the macro will compute an
47/// appropriate inner type to represent the range. This will be the smallest integer type that can
48/// store both the minimum and maximum values, with a preference for unsigned types if both are
49/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
50/// to either or both of the minimum and maximum values, respectively.
51///
52/// # Examples
53///
54/// ```rust,ignore
55/// opt_int!(0, 100); // OptionRangedU8<0, 100>
56/// opt_int!(0i, 100); // OptionRangedI8<0, 100>
57/// opt_int!(-5, 5); // OptionRangedI8<-5, 5>
58/// opt_int!(-5u, 5); // compile error (-5 cannot be unsigned)
59/// ```
60#[cfg(all(docsrs, feature = "macros"))]
61#[macro_export]
62macro_rules! opt_int {
63 ($min:literal, $max:literal) => {};
64}
6566#[cfg(all(not(docsrs), feature = "macros"))]
67pub use deranged_macros::int;
68#[cfg(all(not(docsrs), feature = "macros"))]
69pub use deranged_macros::opt_int;
70#[cfg(feature = "powerfmt")]
71use powerfmt::smart_display;
7273use crate::unsafe_wrapper::Unsafe;
7475/// The error type returned when a checked integral type conversion fails.
76#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TryFromIntError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "TryFromIntError")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TryFromIntError {
#[inline]
fn clone(&self) -> TryFromIntError { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TryFromIntError { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for TryFromIntError {
#[inline]
fn eq(&self, other: &TryFromIntError) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TryFromIntError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq)]
77pub struct TryFromIntError;
7879impl fmt::Displayfor TryFromIntError {
80#[inline]
81fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82f.write_str("out of range integral type conversion attempted")
83 }
84}
85impl Errorfor TryFromIntError {}
8687/// An error which can be returned when parsing an integer.
88///
89/// This error is used as the error type for the `from_str_radix()` functions on ranged integer
90/// types, such as [`RangedI8::from_str_radix`].
91///
92/// # Potential causes
93///
94/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
95/// in the string e.g., when it is obtained from the standard input.
96/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
97///
98/// # Example
99///
100/// ```rust
101/// # use deranged::RangedI32;
102/// if let Err(e) = RangedI32::<0, 10>::from_str_radix("a12", 10) {
103/// println!("Failed conversion to RangedI32: {e}");
104/// }
105/// ```
106#[allow(missing_copy_implementations)] // same as `std`
107#[derive(#[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for ParseIntError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "ParseIntError",
"kind", &&self.kind)
}
}Debug, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::clone::Clone for ParseIntError {
#[inline]
fn clone(&self) -> ParseIntError {
ParseIntError { kind: ::core::clone::Clone::clone(&self.kind) }
}
}Clone, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::cmp::PartialEq for ParseIntError {
#[inline]
fn eq(&self, other: &ParseIntError) -> bool { self.kind == other.kind }
}PartialEq, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::cmp::Eq for ParseIntError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<IntErrorKind>;
}
}Eq)]
108pub struct ParseIntError {
109#[allow(clippy::missing_docs_in_private_items)]
110kind: IntErrorKind,
111}
112113impl ParseIntError {
114/// Outputs the detailed cause of parsing an integer failing.
115// This function is not const because the counterpart of stdlib isn't
116#[allow(clippy::missing_const_for_fn)]
117 #[inline(always)]
118pub fn kind(&self) -> &IntErrorKind {
119&self.kind
120 }
121}
122123impl fmt::Displayfor ParseIntError {
124#[inline]
125fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126match self.kind {
127 IntErrorKind::Empty => "cannot parse integer from empty string",
128 IntErrorKind::InvalidDigit => "invalid digit found in string",
129 IntErrorKind::PosOverflow => "number too large to fit in target type",
130 IntErrorKind::NegOverflow => "number too small to fit in target type",
131 IntErrorKind::Zero => "number would be zero for non-zero type",
132_ => "Unknown Int error kind",
133 }
134 .fmt(f)
135 }
136}
137138impl Errorfor ParseIntError {}
139140/// `?` for `Option` types, usable in `const` contexts.
141macro_rules! const_try_opt {
142 ($e:expr) => {
143match $e {
144Some(value) => value,
145None => return None,
146 }
147 };
148}
149150/// Output the given tokens if the type is signed, otherwise output nothing.
151macro_rules! if_signed {
152 (true $($x:tt)*) => { $($x)*};
153 (false $($x:tt)*) => {};
154}
155156/// Output the given tokens if the type is unsigned, otherwise output nothing.
157macro_rules! if_unsigned {
158 (true $($x:tt)*) => {};
159 (false $($x:tt)*) => { $($x)* };
160}
161162/// `"A"` if `true`, `"An"` if `false`.
163macro_rules! article {
164 (true) => {
165"An"
166};
167 (false) => {
168"A"
169};
170}
171172/// `Option::unwrap_unchecked`, but usable in `const` contexts.
173macro_rules! unsafe_unwrap_unchecked {
174 ($e:expr) => {{
175let opt = $e;
176debug_assert!(opt.is_some());
177match $e {
178Some(value) => value,
179None => core::hint::unreachable_unchecked(),
180 }
181 }};
182}
183184/// Output the provided code if and only if the list does not include `rand_09`.
185#[allow(unused_macro_rules)]
186macro_rules! if_not_manual_rand_09 {
187 ([rand_09 $($rest:ident)*] $($output:tt)*) => {};
188 ([] $($output:tt)*) => {
189 $($output)*
190 };
191 ([$first:ident $($rest:ident)*] $($output:tt)*) => {
192if_not_manual_rand_09!([$($rest)*] $($output)*);
193 };
194}
195196/// Implement a ranged integer type.
197macro_rules! impl_ranged {
198 ($(
199$type:ident {
200 mod_name: $mod_name:ident
201 internal: $internal:ident
202 signed: $is_signed:ident
203 unsigned: $unsigned_type:ident
204 optional: $optional_type:ident
205 from: [$($from:ident($from_internal:ident))+]
206 $(manual: [$($skips:ident)+])?
207}
208 )*) => {$(
209#[doc = concat!(
210article!($is_signed),
211" `",
212stringify!($internal),
213"` that is known to be in the range `MIN..=MAX`.",
214 )]
215 #[repr(transparent)]
216 #[derive(Clone, Copy, Eq, Ord, Hash)]
217pub struct $type<const MIN: $internal, const MAX: $internal>(
218Unsafe<$internal>,
219 );
220221#[doc = concat!(
222"An optional `",
223stringify!($type),
224"`; similar to `Option<",
225stringify!($type),
226">` with better optimization.",
227 )]
228///
229#[doc = concat!(
230"If `MIN` is [`",
231stringify!($internal),
232"::MIN`] _and_ `MAX` is [`",
233stringify!($internal)
234 ,"::MAX`] then compilation will fail. This is because there is no way to represent \
235 the niche value.",
236 )]
237///
238 /// This type is useful when you need to store an optional ranged value in a struct, but
239 /// do not want the overhead of an `Option` type. This reduces the size of the struct
240 /// overall, and is particularly useful when you have a large number of optional fields.
241 /// Note that most operations must still be performed on the [`Option`] type, which is
242#[doc = concat!("obtained with [`", stringify!($optional_type), "::get`].")]
243 #[repr(transparent)]
244 #[derive(Clone, Copy, Eq, Hash)]
245pub struct $optional_type<const MIN: $internal, const MAX: $internal>(
246$internal,
247 );
248249impl $type<0, 0> {
250#[doc = concat!("A ", stringify!($type), " that is always `VALUE`.")]
251 #[inline(always)]
252pub const fn exact<const VALUE: $internal>() -> $type<VALUE, VALUE> {
253// Safety: The value is the only one in range.
254unsafe { $type::new_unchecked(VALUE) }
255 }
256 }
257258if_unsigned! { $is_signed
259impl $type<1, { $internal::MAX }> {
260/// Creates a ranged integer from a non-zero value.
261#[inline(always)]
262pub const fn from_nonzero(value: NonZero<$internal>) -> Self {
263// Safety: The value is non-zero, so it is in range.
264unsafe { Self::new_unchecked(value.get()) }
265 }
266267/// Creates a non-zero value from a ranged integer.
268#[inline(always)]
269pub const fn to_nonzero(self) -> NonZero<$internal> {
270// Safety: The value is in range, so it is non-zero.
271unsafe { NonZero::new_unchecked(self.get()) }
272 }
273 }}
274275impl<const MIN: $internal, const MAX: $internal> $type<MIN, MAX> {
276/// The smallest value that can be represented by this type.
277// Safety: `MIN` is in range by definition.
278pub const MIN: Self = Self::new_static::<MIN>();
279280/// The largest value that can be represented by this type.
281// Safety: `MAX` is in range by definition.
282pub const MAX: Self = Self::new_static::<MAX>();
283284/// Creates a ranged integer without checking the value.
285 ///
286 /// # Safety
287 ///
288 /// The value must be within the range `MIN..=MAX`.
289#[track_caller]
290 #[inline(always)]
291pub const unsafe fn new_unchecked(value: $internal) -> Self {
292const { assert!(MIN <= MAX); }
293// Safety: The caller must ensure that the value is in range.
294unsafe {
295 assert_unchecked(MIN <= value && value <= MAX);
296Self(Unsafe::new(value))
297 }
298 }
299300/// Returns the value as a primitive type.
301 ///
302 /// A call to this function will output a hint to the compiler that the value is in
303 /// range. In general this will help the optimizer to generate better code, but in edge
304 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
305#[doc = concat!("use [`", stringify!($type), "::get_without_hint`].")]
306 #[track_caller]
307 #[inline(always)]
308pub const fn get(self) -> $internal {
309const { assert!(MIN <= MAX); }
310// Safety: A stored value is always in range.
311unsafe { assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX) };
312*self.0.get()
313 }
314315/// Returns the value as a primitive type.
316 ///
317#[doc = concat!("The returned value is identical to [`", stringify!($type), "::get`].")]
318/// Unlike `get`, no hints are output to the compiler indicating the range that the
319 /// value is in. Depending on the scenario, this may with be helpful or harmful too
320 /// optimization.
321#[inline(always)]
322pub const fn get_without_hint(self) -> $internal {
323const { assert!(MIN <= MAX); }
324*self.0.get()
325 }
326327#[track_caller]
328 #[inline(always)]
329pub(crate) const fn get_ref(&self) -> &$internal {
330const { assert!(MIN <= MAX); }
331let value = self.0.get();
332// Safety: A stored value is always in range.
333unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
334 value
335 }
336337/// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
338#[inline(always)]
339pub const fn new(value: $internal) -> Option<Self> {
340const { assert!(MIN <= MAX); }
341if value < MIN || value > MAX {
342None
343} else {
344// Safety: The value is in range.
345Some(unsafe { Self::new_unchecked(value) })
346 }
347 }
348349/// Creates a ranged integer with a statically known value. **Fails to compile** if the
350 /// value is not in range.
351#[inline(always)]
352pub const fn new_static<const VALUE: $internal>() -> Self {
353const {
354assert!(MIN <= VALUE);
355assert!(VALUE <= MAX);
356 }
357// Safety: The value is in range.
358unsafe { Self::new_unchecked(VALUE) }
359 }
360361/// Creates a ranged integer with the given value, saturating if it is out of range.
362#[inline]
363pub const fn new_saturating(value: $internal) -> Self {
364const { assert!(MIN <= MAX); }
365if value < MIN {
366Self::MIN
367 } else if value > MAX {
368Self::MAX
369 } else {
370// Safety: The value is in range.
371unsafe { Self::new_unchecked(value) }
372 }
373 }
374375/// Emit a hint to the compiler that the value is in range.
376 ///
377 /// In some situations, this can help the optimizer to generate better code. In edge
378 /// cases this may lead to **worse** code generation. If you are unsure whether this is
379 /// helpful, harmful, or neutral, you should use [`cargo-show-asm`] to compare the
380 /// generated assembly.
381 ///
382 /// Aside from potentially affecting optimization, this function is a no-op.
383 ///
384 /// [`cargo-show-asm`]: https://crates.io/crates/cargo-show-asm
385#[inline(always)]
386pub const fn emit_range_hint(self) {
387const { assert!(MIN <= MAX); }
388let value = self.0.get();
389// Safety: A stored value is always in range.
390unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
391 }
392393/// Expand the range that the value may be in. **Fails to compile** if the new range is
394 /// not a superset of the current range.
395#[inline(always)]
396pub const fn expand<const NEW_MIN: $internal, const NEW_MAX: $internal>(
397self,
398 ) -> $type<NEW_MIN, NEW_MAX> {
399const {
400assert!(MIN <= MAX);
401assert!(NEW_MIN <= NEW_MAX);
402assert!(NEW_MIN <= MIN);
403assert!(NEW_MAX >= MAX);
404 }
405// Safety: The range is widened.
406unsafe { $type::new_unchecked(self.get()) }
407 }
408409/// Attempt to narrow the range that the value may be in. Returns `None` if the value
410 /// is outside the new range. **Fails to compile** if the new range is not a subset of
411 /// the current range.
412#[inline(always)]
413pub const fn narrow<
414const NEW_MIN: $internal,
415const NEW_MAX: $internal,
416 >(self) -> Option<$type<NEW_MIN, NEW_MAX>> {
417const {
418assert!(MIN <= MAX);
419assert!(NEW_MIN <= NEW_MAX);
420assert!(NEW_MIN >= MIN);
421assert!(NEW_MAX <= MAX);
422 }
423$type::<NEW_MIN, NEW_MAX>::new(self.get())
424 }
425426/// Converts a string slice in a given base to an integer.
427 ///
428 /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
429 /// and trailing whitespace represent an error. Digits are a subset of these characters,
430 /// depending on `radix`:
431 ///
432 /// - `0-9`
433 /// - `a-z`
434 /// - `A-Z`
435 ///
436 /// # Panics
437 ///
438 /// Panics if `radix` is not in the range `2..=36`.
439 ///
440 /// # Examples
441 ///
442 /// Basic usage:
443 ///
444 /// ```rust
445#[doc = concat!("# use deranged::", stringify!($type), ";")]
446 #[doc = concat!(
447"assert_eq!(",
448stringify!($type),
449"::<5, 10>::from_str_radix(\"A\", 16), Ok(",
450stringify!($type),
451"::new_static::<10>()));",
452 )]
453/// ```
454#[inline]
455pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
456const { assert!(MIN <= MAX); }
457match $internal::from_str_radix(src, radix) {
458Ok(value) if value > MAX => {
459Err(ParseIntError { kind: IntErrorKind::PosOverflow })
460 }
461Ok(value) if value < MIN => {
462Err(ParseIntError { kind: IntErrorKind::NegOverflow })
463 }
464// Safety: If the value was out of range, it would have been caught in a
465 // previous arm.
466Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
467Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
468 }
469 }
470471/// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
472 /// value is out of range.
473#[must_use = "this returns the result of the operation, without modifying the original"]
474 #[inline]
475pub const fn checked_add(self, rhs: $internal) -> Option<Self> {
476const { assert!(MIN <= MAX); }
477Self::new(const_try_opt!(self.get().checked_add(rhs)))
478 }
479480/// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
481 /// range.
482 ///
483 /// # Safety
484 ///
485 /// The result of `self + rhs` must be in the range `MIN..=MAX`.
486#[must_use = "this returns the result of the operation, without modifying the original"]
487 #[track_caller]
488 #[inline(always)]
489pub const unsafe fn unchecked_add(self, rhs: $internal) -> Self {
490const { assert!(MIN <= MAX); }
491// Safety: The caller must ensure that the result is in range.
492unsafe {
493Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_add(rhs)))
494 }
495 }
496497/// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
498 /// value is out of range.
499#[must_use = "this returns the result of the operation, without modifying the original"]
500 #[inline]
501pub const fn checked_sub(self, rhs: $internal) -> Option<Self> {
502const { assert!(MIN <= MAX); }
503Self::new(const_try_opt!(self.get().checked_sub(rhs)))
504 }
505506/// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
507 /// range.
508 ///
509 /// # Safety
510 ///
511 /// The result of `self - rhs` must be in the range `MIN..=MAX`.
512#[must_use = "this returns the result of the operation, without modifying the original"]
513 #[track_caller]
514 #[inline(always)]
515pub const unsafe fn unchecked_sub(self, rhs: $internal) -> Self {
516const { assert!(MIN <= MAX); }
517// Safety: The caller must ensure that the result is in range.
518unsafe {
519Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_sub(rhs)))
520 }
521 }
522523/// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
524 /// value is out of range.
525#[must_use = "this returns the result of the operation, without modifying the original"]
526 #[inline]
527pub const fn checked_mul(self, rhs: $internal) -> Option<Self> {
528const { assert!(MIN <= MAX); }
529Self::new(const_try_opt!(self.get().checked_mul(rhs)))
530 }
531532/// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
533 /// in range.
534 ///
535 /// # Safety
536 ///
537 /// The result of `self * rhs` must be in the range `MIN..=MAX`.
538#[must_use = "this returns the result of the operation, without modifying the original"]
539 #[track_caller]
540 #[inline(always)]
541pub const unsafe fn unchecked_mul(self, rhs: $internal) -> Self {
542const { assert!(MIN <= MAX); }
543// Safety: The caller must ensure that the result is in range.
544unsafe {
545Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_mul(rhs)))
546 }
547 }
548549/// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
550 /// if the resulting value is out of range.
551#[must_use = "this returns the result of the operation, without modifying the original"]
552 #[inline]
553pub const fn checked_div(self, rhs: $internal) -> Option<Self> {
554const { assert!(MIN <= MAX); }
555Self::new(const_try_opt!(self.get().checked_div(rhs)))
556 }
557558/// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
559 /// the result is in range.
560 ///
561 /// # Safety
562 ///
563 /// `self` must not be zero and the result of `self / rhs` must be in the range
564 /// `MIN..=MAX`.
565#[must_use = "this returns the result of the operation, without modifying the original"]
566 #[track_caller]
567 #[inline(always)]
568pub const unsafe fn unchecked_div(self, rhs: $internal) -> Self {
569const { assert!(MIN <= MAX); }
570// Safety: The caller must ensure that the result is in range and that `rhs` is not
571 // zero.
572unsafe {
573Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_div(rhs)))
574 }
575 }
576577/// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
578 /// `rhs == 0` or if the resulting value is out of range.
579#[must_use = "this returns the result of the operation, without modifying the original"]
580 #[inline]
581pub const fn checked_div_euclid(self, rhs: $internal) -> Option<Self> {
582const { assert!(MIN <= MAX); }
583Self::new(const_try_opt!(self.get().checked_div_euclid(rhs)))
584 }
585586/// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
587 /// `rhs != 0` and that the result is in range.
588 ///
589 /// # Safety
590 ///
591 /// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
592 /// range `MIN..=MAX`.
593#[must_use = "this returns the result of the operation, without modifying the original"]
594 #[track_caller]
595 #[inline(always)]
596pub const unsafe fn unchecked_div_euclid(self, rhs: $internal) -> Self {
597const { assert!(MIN <= MAX); }
598// Safety: The caller must ensure that the result is in range and that `rhs` is not
599 // zero.
600unsafe {
601Self::new_unchecked(
602unsafe_unwrap_unchecked!(self.get().checked_div_euclid(rhs))
603 )
604 }
605 }
606607if_unsigned!($is_signed
608/// Remainder. Computes `self % rhs`, statically guaranteeing that the returned value
609 /// is in range.
610#[must_use = "this returns the result of the operation, without modifying the original"]
611 #[track_caller]
612 #[inline]
613pub const fn rem<const RHS_VALUE: $internal>(
614self,
615 rhs: $type<RHS_VALUE, RHS_VALUE>,
616 ) -> $type<0, RHS_VALUE> {
617const { assert!(MIN <= MAX); }
618// Safety: The result is guaranteed to be in range due to the nature of remainder on
619 // unsigned integers.
620unsafe { $type::new_unchecked(self.get() % rhs.get()) }
621 });
622623/// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
624 /// if the resulting value is out of range.
625#[must_use = "this returns the result of the operation, without modifying the original"]
626 #[inline]
627pub const fn checked_rem(self, rhs: $internal) -> Option<Self> {
628const { assert!(MIN <= MAX); }
629Self::new(const_try_opt!(self.get().checked_rem(rhs)))
630 }
631632/// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
633 /// result is in range.
634 ///
635 /// # Safety
636 ///
637 /// `self` must not be zero and the result of `self % rhs` must be in the range
638 /// `MIN..=MAX`.
639#[must_use = "this returns the result of the operation, without modifying the original"]
640 #[track_caller]
641 #[inline(always)]
642pub const unsafe fn unchecked_rem(self, rhs: $internal) -> Self {
643const { assert!(MIN <= MAX); }
644// Safety: The caller must ensure that the result is in range and that `rhs` is not
645 // zero.
646unsafe {
647Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_rem(rhs)))
648 }
649 }
650651/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
652 /// `rhs == 0` or if the resulting value is out of range.
653#[must_use = "this returns the result of the operation, without modifying the original"]
654 #[inline]
655pub const fn checked_rem_euclid(self, rhs: $internal) -> Option<Self> {
656const { assert!(MIN <= MAX); }
657Self::new(const_try_opt!(self.get().checked_rem_euclid(rhs)))
658 }
659660/// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
661 /// `rhs != 0` and that the result is in range.
662 ///
663 /// # Safety
664 ///
665 /// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
666 /// range `MIN..=MAX`.
667#[must_use = "this returns the result of the operation, without modifying the original"]
668 #[track_caller]
669 #[inline(always)]
670pub const unsafe fn unchecked_rem_euclid(self, rhs: $internal) -> Self {
671const { assert!(MIN <= MAX); }
672// Safety: The caller must ensure that the result is in range and that `rhs` is not
673 // zero.
674unsafe {
675Self::new_unchecked(
676unsafe_unwrap_unchecked!(self.get().checked_rem_euclid(rhs))
677 )
678 }
679 }
680681/// Checked negation. Computes `-self`, returning `None` if the resulting value is out
682 /// of range.
683#[must_use = "this returns the result of the operation, without modifying the original"]
684 #[inline]
685pub const fn checked_neg(self) -> Option<Self> {
686const { assert!(MIN <= MAX); }
687Self::new(const_try_opt!(self.get().checked_neg()))
688 }
689690/// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
691 ///
692 /// # Safety
693 ///
694 /// The result of `-self` must be in the range `MIN..=MAX`.
695#[must_use = "this returns the result of the operation, without modifying the original"]
696 #[track_caller]
697 #[inline(always)]
698pub const unsafe fn unchecked_neg(self) -> Self {
699const { assert!(MIN <= MAX); }
700// Safety: The caller must ensure that the result is in range.
701unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_neg())) }
702 }
703704/// Negation. Computes `self.neg()`, **failing to compile** if the result is not
705 /// guaranteed to be in range.
706#[must_use = "this returns the result of the operation, without modifying the original"]
707 #[inline(always)]
708pub const fn neg(self) -> Self {
709const {
710assert!(MIN <= MAX);
711if_signed! { $is_signed
712assert!(MIN != $internal::MIN);
713assert!(-MIN <= MAX);
714assert!(-MAX >= MIN);
715 }
716if_unsigned! { $is_signed
717assert!(MAX == 0);
718 }
719 }
720// Safety: The compiler asserts that the result is in range.
721unsafe { self.unchecked_neg() }
722 }
723724/// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
725 /// is out of range.
726#[must_use = "this returns the result of the operation, without modifying the original"]
727 #[inline]
728pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
729const { assert!(MIN <= MAX); }
730Self::new(const_try_opt!(self.get().checked_shl(rhs)))
731 }
732733/// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
734 ///
735 /// # Safety
736 ///
737 /// The result of `self << rhs` must be in the range `MIN..=MAX`.
738#[must_use = "this returns the result of the operation, without modifying the original"]
739 #[track_caller]
740 #[inline(always)]
741pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
742const { assert!(MIN <= MAX); }
743// Safety: The caller must ensure that the result is in range.
744unsafe {
745Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shl(rhs)))
746 }
747 }
748749/// Checked shift right. Computes `self >> rhs`, returning `None` if
750 /// the resulting value is out of range.
751#[must_use = "this returns the result of the operation, without modifying the original"]
752 #[inline]
753pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
754const { assert!(MIN <= MAX); }
755Self::new(const_try_opt!(self.get().checked_shr(rhs)))
756 }
757758/// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
759 ///
760 /// # Safety
761 ///
762 /// The result of `self >> rhs` must be in the range `MIN..=MAX`.
763#[must_use = "this returns the result of the operation, without modifying the original"]
764 #[track_caller]
765 #[inline(always)]
766pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
767const { assert!(MIN <= MAX); }
768// Safety: The caller must ensure that the result is in range.
769unsafe {
770Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shr(rhs)))
771 }
772 }
773774if_signed!($is_signed
775/// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
776 /// value is out of range.
777#[must_use = "this returns the result of the operation, without modifying the original"]
778 #[inline]
779pub const fn checked_abs(self) -> Option<Self> {
780const { assert!(MIN <= MAX); }
781Self::new(const_try_opt!(self.get().checked_abs()))
782 }
783784/// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
785 /// range.
786 ///
787 /// # Safety
788 ///
789 /// The result of `self.abs()` must be in the range `MIN..=MAX`.
790#[must_use = "this returns the result of the operation, without modifying the original"]
791 #[track_caller]
792 #[inline(always)]
793pub const unsafe fn unchecked_abs(self) -> Self {
794const { assert!(MIN <= MAX); }
795// Safety: The caller must ensure that the result is in range.
796unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_abs())) }
797 }
798799/// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
800 /// guaranteed to be in range.
801#[must_use = "this returns the result of the operation, without modifying the original"]
802 #[inline(always)]
803pub const fn abs(self) -> Self {
804const {
805assert!(MIN <= MAX);
806assert!(MIN != $internal::MIN);
807assert!(-MIN <= MAX);
808 }
809// <Self as $crate::traits::AbsIsSafe>::ASSERT;
810 // Safety: The compiler asserts that the result is in range.
811unsafe { self.unchecked_abs() }
812 });
813814/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
815 /// value is out of range.
816#[must_use = "this returns the result of the operation, without modifying the original"]
817 #[inline]
818pub const fn checked_pow(self, exp: u32) -> Option<Self> {
819const { assert!(MIN <= MAX); }
820Self::new(const_try_opt!(self.get().checked_pow(exp)))
821 }
822823/// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
824 /// range.
825 ///
826 /// # Safety
827 ///
828 /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
829#[must_use = "this returns the result of the operation, without modifying the original"]
830 #[track_caller]
831 #[inline(always)]
832pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
833const { assert!(MIN <= MAX); }
834// Safety: The caller must ensure that the result is in range.
835unsafe {
836Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_pow(exp)))
837 }
838 }
839840/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
841 /// bounds.
842#[must_use = "this returns the result of the operation, without modifying the original"]
843 #[inline]
844pub const fn saturating_add(self, rhs: $internal) -> Self {
845const { assert!(MIN <= MAX); }
846Self::new_saturating(self.get().saturating_add(rhs))
847 }
848849/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
850 /// bounds.
851#[must_use = "this returns the result of the operation, without modifying the original"]
852 #[inline]
853pub const fn saturating_sub(self, rhs: $internal) -> Self {
854const { assert!(MIN <= MAX); }
855Self::new_saturating(self.get().saturating_sub(rhs))
856 }
857858if_signed!($is_signed
859/// Saturating integer negation. Computes `self - rhs`, saturating at the numeric
860 /// bounds.
861#[must_use = "this returns the result of the operation, without modifying the original"]
862 #[inline]
863pub const fn saturating_neg(self) -> Self {
864const { assert!(MIN <= MAX); }
865Self::new_saturating(self.get().saturating_neg())
866 });
867868if_signed!($is_signed
869/// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
870#[must_use = "this returns the result of the operation, without modifying the original"]
871 #[inline]
872pub const fn saturating_abs(self) -> Self {
873const { assert!(MIN <= MAX); }
874Self::new_saturating(self.get().saturating_abs())
875 });
876877/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
878 /// bounds.
879#[must_use = "this returns the result of the operation, without modifying the original"]
880 #[inline]
881pub const fn saturating_mul(self, rhs: $internal) -> Self {
882const { assert!(MIN <= MAX); }
883Self::new_saturating(self.get().saturating_mul(rhs))
884 }
885886/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
887 /// numeric bounds.
888#[must_use = "this returns the result of the operation, without modifying the original"]
889 #[inline]
890pub const fn saturating_pow(self, exp: u32) -> Self {
891const { assert!(MIN <= MAX); }
892Self::new_saturating(self.get().saturating_pow(exp))
893 }
894895if_signed! { $is_signed
896/// Returns `true` if the number is positive and `false` if the number is zero or
897 /// negative.
898#[inline]
899pub const fn is_positive(self) -> bool {
900const { assert!(MIN <= MAX); }
901self.get().is_positive()
902 }
903904/// Returns `true` if the number is negative and `false` if the number is zero or
905 /// positive.
906#[inline]
907pub const fn is_negative(self) -> bool {
908const { assert!(MIN <= MAX); }
909self.get().is_negative()
910 }
911 }
912913/// Compute the `rem_euclid` of this type with its unsigned type equivalent
914// Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
915 // Also because this isn't implemented for normal types in std.
916#[must_use = "this returns the result of the operation, without modifying the original"]
917 #[track_caller]
918 #[inline]
919 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
920const fn rem_euclid_unsigned(
921 rhs: $internal,
922 range_len: $unsigned_type
923) -> $unsigned_type {
924#[allow(unused_comparisons)]
925if rhs >= 0 {
926 (rhs as $unsigned_type) % range_len
927 } else {
928// Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
929 // Can't write -ux or ux::abs() method. This gets around compilation error.
930 // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
931let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
932// Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
933 // Also = 0 in mod range_len arithmetic.
934 // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
935 // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
936 // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
937 // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
938((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
939 }
940 }
941942/// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
943 /// bounds.
944#[must_use = "this returns the result of the operation, without modifying the original"]
945 #[inline]
946 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
947pub const fn wrapping_add(self, rhs: $internal) -> Self {
948const { assert!(MIN <= MAX); }
949// Forward to internal type's impl if same as type.
950if MIN == $internal::MIN && MAX == $internal::MAX {
951// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
952return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
953 }
954955let inner = self.get();
956957// Won't overflow because of std impl forwarding.
958let range_len = MAX.abs_diff(MIN) + 1;
959960// Calculate the offset with proper handling for negative rhs
961let offset = Self::rem_euclid_unsigned(rhs, range_len);
962963let greater_vals = MAX.abs_diff(inner);
964// No wrap
965if offset <= greater_vals {
966// Safety:
967 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
968 // if inner < 0: Same as >=0 with caveat:
969 // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
970 // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
971 // (the difference doesn't matter since it won't overflow),
972 // but unsigned integers don't have either method so it won't compile that way.
973unsafe { Self::new_unchecked(
974 ((inner as $unsigned_type).wrapping_add(offset)) as $internal
975) }
976 }
977// Wrap
978else {
979// Safety:
980 // - offset < range_len by rem_euclid (MIN + ... safe)
981 // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
982 //
983 // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
984unsafe { Self::new_unchecked(
985 ((MIN as $unsigned_type).wrapping_add(
986 offset - (greater_vals + 1)
987 )) as $internal
988) }
989 }
990 }
991992/// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
993 /// bounds.
994#[must_use = "this returns the result of the operation, without modifying the original"]
995 #[inline]
996 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
997pub const fn wrapping_sub(self, rhs: $internal) -> Self {
998const { assert!(MIN <= MAX); }
999// Forward to internal type's impl if same as type.
1000if MIN == $internal::MIN && MAX == $internal::MAX {
1001// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1002return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
1003 }
10041005let inner = self.get();
10061007// Won't overflow because of std impl forwarding.
1008let range_len = MAX.abs_diff(MIN) + 1;
10091010// Calculate the offset with proper handling for negative rhs
1011let offset = Self::rem_euclid_unsigned(rhs, range_len);
10121013let lesser_vals = MIN.abs_diff(inner);
1014// No wrap
1015if offset <= lesser_vals {
1016// Safety:
1017 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1018 // if inner < 0: Same as >=0 with caveat:
1019 // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
1020 // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
1021 // (the difference doesn't matter since it won't overflow below 0),
1022 // but unsigned integers don't have either method so it won't compile that way.
1023unsafe { Self::new_unchecked(
1024 ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
1025) }
1026 }
1027// Wrap
1028else {
1029// Safety:
1030 // - offset < range_len by rem_euclid (MAX - ... safe)
1031 // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
1032 //
1033 // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
1034unsafe { Self::new_unchecked(
1035 ((MAX as $unsigned_type).wrapping_sub(
1036 offset - (lesser_vals + 1)
1037 )) as $internal
1038) }
1039 }
1040 }
1041 }
10421043impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
1044/// The value used as the niche. Must not be in the range `MIN..=MAX`.
1045const NICHE: $internal = match (MIN, MAX) {
1046 ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
1047 ($internal::MIN, _) => $internal::MAX,
1048 (_, _) => $internal::MIN,
1049 };
10501051/// An optional ranged value that is not present.
1052#[allow(non_upper_case_globals)]
1053pub const None: Self = Self(Self::NICHE);
10541055/// Creates an optional ranged value that is present.
1056#[allow(non_snake_case)]
1057 #[inline(always)]
1058pub const fn Some(value: $type<MIN, MAX>) -> Self {
1059const { assert!(MIN <= MAX); }
1060Self(value.get())
1061 }
10621063/// Returns the value as the standard library's [`Option`] type.
1064#[inline(always)]
1065pub const fn get(self) -> Option<$type<MIN, MAX>> {
1066const { assert!(MIN <= MAX); }
1067if self.0 == Self::NICHE {
1068None
1069} else {
1070// Safety: A stored value that is not the niche is always in range.
1071Some(unsafe { $type::new_unchecked(self.0) })
1072 }
1073 }
10741075/// Creates an optional ranged integer without checking the value.
1076 ///
1077 /// # Safety
1078 ///
1079 /// The value must be within the range `MIN..=MAX`. As the value used for niche
1080 /// value optimization is unspecified, the provided value must not be the niche
1081 /// value.
1082#[inline(always)]
1083 #[track_caller]
1084pub const unsafe fn some_unchecked(value: $internal) -> Self {
1085const { assert!(MIN <= MAX); }
1086// Safety: The caller must ensure that the value is in range.
1087unsafe { assert_unchecked(MIN <= value && value <= MAX) };
1088Self(value)
1089 }
10901091/// Obtain the inner value of the struct. This is useful for comparisons.
1092#[inline(always)]
1093pub(crate) const fn inner(self) -> $internal {
1094const { assert!(MIN <= MAX); }
1095self.0
1096}
10971098/// Obtain the value of the struct as an `Option` of the primitive type.
1099 ///
1100 /// A call to this function will output a hint to the compiler that the value is in
1101 /// range. In general this will help the optimizer to generate better code, but in edge
1102 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
1103#[doc = concat!(
1104"use [`", stringify!($optional_type), "::get_primitive_without_hint`]."
1105)]
1106 #[inline(always)]
1107pub const fn get_primitive(self) -> Option<$internal> {
1108const { assert!(MIN <= MAX); }
1109Some(const_try_opt!(self.get()).get())
1110 }
11111112/// Obtain the value of the struct as an `Option` of the primitive type.
1113 ///
1114#[doc = concat!(
1115"The returned value is identical to [`", stringify!($optional_type), "::",
1116"get_primitive`]."
1117)]
1118/// Unlike `get_primitive`, no hints are output to the compiler indicating the range
1119 /// that the value is in. Depending on the scenario, this may with be helpful or harmful
1120 /// too optimization.
1121#[inline(always)]
1122pub const fn get_primitive_without_hint(self) -> Option<$internal> {
1123const { assert!(MIN <= MAX); }
1124Some(const_try_opt!(self.get()).get_without_hint())
1125 }
11261127/// Returns `true` if the value is the niche value.
1128#[inline(always)]
1129pub const fn is_none(&self) -> bool {
1130const { assert!(MIN <= MAX); }
1131self.get().is_none()
1132 }
11331134/// Returns `true` if the value is not the niche value.
1135#[inline(always)]
1136pub const fn is_some(&self) -> bool {
1137const { assert!(MIN <= MAX); }
1138self.get().is_some()
1139 }
1140 }
11411142impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
1143#[inline(always)]
1144fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145const { assert!(MIN <= MAX); }
1146self.get().fmt(f)
1147 }
1148 }
11491150impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
1151#[inline(always)]
1152fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1153const { assert!(MIN <= MAX); }
1154self.get().fmt(f)
1155 }
1156 }
11571158impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
1159#[inline(always)]
1160fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1161const { assert!(MIN <= MAX); }
1162self.get().fmt(f)
1163 }
1164 }
11651166#[cfg(feature = "powerfmt")]
1167impl<
1168const MIN: $internal,
1169const MAX: $internal,
1170 > smart_display::SmartDisplay for $type<MIN, MAX> {
1171type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
11721173#[inline(always)]
1174fn metadata(
1175&self,
1176 f: smart_display::FormatterOptions,
1177 ) -> smart_display::Metadata<'_, Self> {
1178const { assert!(MIN <= MAX); }
1179self.get_ref().metadata(f).reuse()
1180 }
11811182#[inline(always)]
1183fn fmt_with_metadata(
1184&self,
1185 f: &mut fmt::Formatter<'_>,
1186 metadata: smart_display::Metadata<'_, Self>,
1187 ) -> fmt::Result {
1188const { assert!(MIN <= MAX); }
1189self.get().fmt_with_metadata(f, metadata.reuse())
1190 }
1191 }
11921193impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
1194#[inline(always)]
1195fn default() -> Self {
1196const { assert!(MIN <= MAX); }
1197Self::None
1198 }
1199 }
12001201impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
1202#[inline(always)]
1203fn as_ref(&self) -> &$internal {
1204const { assert!(MIN <= MAX); }
1205&self.get_ref()
1206 }
1207 }
12081209impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
1210#[inline(always)]
1211fn borrow(&self) -> &$internal {
1212const { assert!(MIN <= MAX); }
1213&self.get_ref()
1214 }
1215 }
12161217impl<
1218const MIN_A: $internal,
1219const MAX_A: $internal,
1220const MIN_B: $internal,
1221const MAX_B: $internal,
1222 > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1223#[inline(always)]
1224fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
1225const {
1226assert!(MIN_A <= MAX_A);
1227assert!(MIN_B <= MAX_B);
1228 }
1229self.get() == other.get()
1230 }
1231 }
12321233impl<
1234const MIN_A: $internal,
1235const MAX_A: $internal,
1236const MIN_B: $internal,
1237const MAX_B: $internal,
1238 > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1239#[inline(always)]
1240fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
1241const {
1242assert!(MIN_A <= MAX_A);
1243assert!(MIN_B <= MAX_B);
1244 }
1245self.inner() == other.inner()
1246 }
1247 }
12481249impl<
1250const MIN_A: $internal,
1251const MAX_A: $internal,
1252const MIN_B: $internal,
1253const MAX_B: $internal,
1254 > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1255#[inline(always)]
1256fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
1257const {
1258assert!(MIN_A <= MAX_A);
1259assert!(MIN_B <= MAX_B);
1260 }
1261self.get().partial_cmp(&other.get())
1262 }
1263 }
12641265impl<
1266const MIN_A: $internal,
1267const MAX_A: $internal,
1268const MIN_B: $internal,
1269const MAX_B: $internal,
1270 > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1271#[inline]
1272fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
1273const {
1274assert!(MIN_A <= MAX_A);
1275assert!(MIN_B <= MAX_B);
1276 }
1277if self.is_none() && other.is_none() {
1278Some(Ordering::Equal)
1279 } else if self.is_none() {
1280Some(Ordering::Less)
1281 } else if other.is_none() {
1282Some(Ordering::Greater)
1283 } else {
1284self.inner().partial_cmp(&other.inner())
1285 }
1286 }
1287 }
12881289impl<
1290const MIN: $internal,
1291const MAX: $internal,
1292 > Ord for $optional_type<MIN, MAX> {
1293#[inline]
1294fn cmp(&self, other: &Self) -> Ordering {
1295const { assert!(MIN <= MAX); }
1296if self.is_none() && other.is_none() {
1297 Ordering::Equal
1298 } else if self.is_none() {
1299 Ordering::Less
1300 } else if other.is_none() {
1301 Ordering::Greater
1302 } else {
1303self.inner().cmp(&other.inner())
1304 }
1305 }
1306 }
13071308impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
1309#[inline(always)]
1310fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1311const { assert!(MIN <= MAX); }
1312self.get().fmt(f)
1313 }
1314 }
13151316impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
1317#[inline(always)]
1318fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1319const { assert!(MIN <= MAX); }
1320self.get().fmt(f)
1321 }
1322 }
13231324impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
1325#[inline(always)]
1326fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1327const { assert!(MIN <= MAX); }
1328self.get().fmt(f)
1329 }
1330 }
13311332impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
1333#[inline(always)]
1334fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1335const { assert!(MIN <= MAX); }
1336self.get().fmt(f)
1337 }
1338 }
13391340impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
1341#[inline(always)]
1342fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1343const { assert!(MIN <= MAX); }
1344self.get().fmt(f)
1345 }
1346 }
13471348impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
1349#[inline(always)]
1350fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1351const { assert!(MIN <= MAX); }
1352self.get().fmt(f)
1353 }
1354 }
13551356if_unsigned! { $is_signed
1357impl From<NonZero<$internal>> for $type<1, { $internal::MAX }> {
1358#[inline(always)]
1359fn from(value: NonZero<$internal>) -> Self {
1360Self::from_nonzero(value)
1361 }
1362 }
13631364impl From<$type<1, { $internal::MAX }>> for NonZero<$internal> {
1365#[inline(always)]
1366fn from(value: $type<1, { $internal::MAX }>) -> Self {
1367 value.to_nonzero()
1368 }
1369 }
1370 }
13711372impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
1373#[inline(always)]
1374fn from(value: $type<MIN, MAX>) -> Self {
1375const { assert!(MIN <= MAX); }
1376 value.get()
1377 }
1378 }
13791380impl<
1381const MIN: $internal,
1382const MAX: $internal,
1383 > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
1384#[inline(always)]
1385fn from(value: $type<MIN, MAX>) -> Self {
1386const { assert!(MIN <= MAX); }
1387Self::Some(value)
1388 }
1389 }
13901391impl<
1392const MIN: $internal,
1393const MAX: $internal,
1394 > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
1395#[inline(always)]
1396fn from(value: Option<$type<MIN, MAX>>) -> Self {
1397const { assert!(MIN <= MAX); }
1398match value {
1399Some(value) => Self::Some(value),
1400None => Self::None,
1401 }
1402 }
1403 }
14041405impl<
1406const MIN: $internal,
1407const MAX: $internal,
1408 > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
1409#[inline(always)]
1410fn from(value: $optional_type<MIN, MAX>) -> Self {
1411const { assert!(MIN <= MAX); }
1412 value.get()
1413 }
1414 }
14151416impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
1417type Error = TryFromIntError;
14181419#[inline]
1420fn try_from(value: $internal) -> Result<Self, Self::Error> {
1421const { assert!(MIN <= MAX); }
1422Self::new(value).ok_or(TryFromIntError)
1423 }
1424 }
14251426impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
1427type Err = ParseIntError;
14281429#[inline]
1430fn from_str(s: &str) -> Result<Self, Self::Err> {
1431const { assert!(MIN <= MAX); }
1432let value = s.parse::<$internal>().map_err(|e| ParseIntError {
1433 kind: e.kind().clone()
1434 })?;
1435if value < MIN {
1436Err(ParseIntError { kind: IntErrorKind::NegOverflow })
1437 } else if value > MAX {
1438Err(ParseIntError { kind: IntErrorKind::PosOverflow })
1439 } else {
1440// Safety: The value was previously checked for validity.
1441Ok(unsafe { Self::new_unchecked(value) })
1442 }
1443 }
1444 }
14451446 $(impl<
1447const MIN_SRC: $from_internal,
1448const MAX_SRC: $from_internal,
1449const MIN_DST: $internal,
1450const MAX_DST: $internal,
1451 > From<$from<MIN_SRC, MAX_SRC>> for $type<MIN_DST, MAX_DST>
1452 {
1453#[inline(always)]
1454 #[allow(trivial_numeric_casts, unused_comparisons)]
1455fn from(value: $from<MIN_SRC, MAX_SRC>) -> Self {
1456const {
1457assert!(MIN_SRC <= MAX_SRC, "source range is invalid");
1458assert!(MIN_DST <= MAX_DST, "target range is invalid");
14591460match ($from_internal::MIN == 0, $internal::MIN == 0) {
1461// unsigned -> unsigned
1462(true, true) => {
1463assert!(
1464 MIN_SRC as u128 >= MIN_DST as u128,
1465"minimum value cannot be represented in the target range"
1466);
1467assert!(
1468 MAX_SRC as u128 <= MAX_DST as u128,
1469"maximum value cannot be represented in the target range"
1470);
1471 }
1472// signed -> signed
1473(false, false) => {
1474assert!(
1475 MIN_SRC as i128 >= MIN_DST as i128,
1476"minimum value cannot be represented in the target range"
1477);
1478assert!(
1479 MAX_SRC as i128 <= MAX_DST as i128,
1480"maximum value cannot be represented in the target range"
1481);
1482 }
1483// unsigned -> signed
1484(true, false) => {
1485assert!(
1486 MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128,
1487"minimum value cannot be represented in the target range"
1488);
1489assert!(
1490 MAX_DST >= 0
1491&& MAX_SRC as u128 <= i128::MAX as u128
1492 && MAX_SRC as i128 <= MAX_DST as i128,
1493"maximum value cannot be represented in the target range"
1494);
1495 }
1496// signed -> unsigned
1497(false, true) => {
1498assert!(
1499 MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128,
1500"minimum value cannot be represented in the target range"
1501);
1502assert!(
1503 MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128,
1504"maximum value cannot be represented in the target range"
1505);
1506 }
1507 }
1508 }
15091510// Safety: The source range is a subset of the destination range.
1511unsafe { $type::new_unchecked(value.get() as $internal) }
1512 }
1513 })+
15141515#[cfg(feature = "serde")]
1516impl<const MIN: $internal, const MAX: $internal> serde_core::Serialize for $type<MIN, MAX> {
1517#[inline(always)]
1518fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1519 {
1520const { assert!(MIN <= MAX); }
1521self.get().serialize(serializer)
1522 }
1523 }
15241525#[cfg(feature = "serde")]
1526impl<
1527const MIN: $internal,
1528const MAX: $internal,
1529 > serde_core::Serialize for $optional_type<MIN, MAX> {
1530#[inline(always)]
1531fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1532 {
1533const { assert!(MIN <= MAX); }
1534self.get().serialize(serializer)
1535 }
1536 }
15371538#[cfg(feature = "serde")]
1539impl<
1540'de,
1541const MIN: $internal,
1542const MAX: $internal,
1543 > serde_core::Deserialize<'de> for $type<MIN, MAX> {
1544#[inline]
1545fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1546 -> Result<Self, D::Error>
1547 {
1548const { assert!(MIN <= MAX); }
1549let internal = <$internal>::deserialize(deserializer)?;
1550Self::new(internal).ok_or_else(||
1551 <D::Error as serde_core::de::Error>::invalid_value(
1552 serde_core::de::Unexpected::Other("integer"),
1553#[cfg(feature = "alloc")] {
1554&alloc::format!("an integer in the range {}..={}", MIN, MAX).as_ref()
1555 },
1556#[cfg(not(feature = "alloc"))] {
1557&"an integer in the valid range"
1558}
1559 )
1560 )
1561 }
1562 }
15631564#[cfg(feature = "serde")]
1565impl<
1566'de,
1567const MIN: $internal,
1568const MAX: $internal,
1569 > serde_core::Deserialize<'de> for $optional_type<MIN, MAX> {
1570#[inline]
1571fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1572 -> Result<Self, D::Error>
1573 {
1574const { assert!(MIN <= MAX); }
1575Ok(Self::Some($type::<MIN, MAX>::deserialize(deserializer)?))
1576 }
1577 }
15781579#[cfg(feature = "rand08")]
1580impl<
1581const MIN: $internal,
1582const MAX: $internal,
1583 > rand08::distributions::Distribution<$type<MIN, MAX>> for rand08::distributions::Standard {
1584#[inline]
1585fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1586const { assert!(MIN <= MAX); }
1587$type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1588 }
1589 }
15901591if_not_manual_rand_09! {
1592 [$($($skips)+)?]
1593#[cfg(feature = "rand09")]
1594impl<
1595const MIN: $internal,
1596const MAX: $internal,
1597 > rand09::distr::Distribution<$type<MIN, MAX>> for rand09::distr::StandardUniform {
1598#[inline]
1599fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1600const { assert!(MIN <= MAX); }
1601$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1602 }
1603 }
1604 }
16051606#[cfg(feature = "rand08")]
1607impl<
1608const MIN: $internal,
1609const MAX: $internal,
1610 > rand08::distributions::Distribution<$optional_type<MIN, MAX>>
1611for rand08::distributions::Standard {
1612#[inline]
1613fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1614const { assert!(MIN <= MAX); }
1615 rng.r#gen::<Option<$type<MIN, MAX>>>().into()
1616 }
1617 }
16181619#[cfg(feature = "rand09")]
1620impl<
1621const MIN: $internal,
1622const MAX: $internal,
1623 > rand09::distr::Distribution<$optional_type<MIN, MAX>>
1624for rand09::distr::StandardUniform {
1625#[inline]
1626fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1627const { assert!(MIN <= MAX); }
1628if rng.random() {
1629$optional_type::None
1630} else {
1631$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1632 }
1633 }
1634 }
16351636#[cfg(feature = "num")]
1637impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
1638#[inline(always)]
1639fn min_value() -> Self {
1640const { assert!(MIN <= MAX); }
1641Self::MIN
1642 }
16431644#[inline(always)]
1645fn max_value() -> Self {
1646const { assert!(MIN <= MAX); }
1647Self::MAX
1648 }
1649 }
16501651#[cfg(feature = "quickcheck")]
1652impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
1653#[inline]
1654fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1655const { assert!(MIN <= MAX); }
1656// Safety: The `rem_euclid` call and addition ensure that the value is in range.
1657unsafe {
1658Self::new_unchecked($internal::arbitrary(g).rem_euclid(MAX - MIN + 1) + MIN)
1659 }
1660 }
16611662#[inline]
1663fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1664 ::alloc::boxed::Box::new(
1665self.get()
1666 .shrink()
1667 .filter_map(Self::new)
1668 )
1669 }
1670 }
16711672#[cfg(feature = "quickcheck")]
1673impl<
1674const MIN: $internal,
1675const MAX: $internal,
1676 > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
1677#[inline]
1678fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1679const { assert!(MIN <= MAX); }
1680Option::<$type<MIN, MAX>>::arbitrary(g).into()
1681 }
16821683#[inline]
1684fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1685 ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
1686 }
1687 }
1688 )*};
1689}
16901691#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::clone::Clone for
RangedIsize<MIN, MAX> {
#[inline]
fn clone(&self) -> RangedIsize<MIN, MAX> {
let _: ::core::clone::AssertParamIsClone<Unsafe<isize>>;
*self
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::marker::Copy for
RangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Eq for
RangedIsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<Unsafe<isize>>;
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Ord for
RangedIsize<MIN, MAX> {
#[inline]
fn cmp(&self, other: &RangedIsize<MIN, MAX>) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::hash::Hash for
RangedIsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedIsize`; similar to `Option<RangedIsize>` with better optimization."]
///
#[doc =
"If `MIN` is [`isize::MIN`] _and_ `MAX` is [`isize::MAX`] then compilation will fail. This is because there is no way to represent the niche value."]
///
/// This type is useful when you need to store an optional ranged value in a struct, but
/// do not want the overhead of an `Option` type. This reduces the size of the struct
/// overall, and is particularly useful when you have a large number of optional fields.
/// Note that most operations must still be performed on the [`Option`] type, which is
#[doc = "obtained with [`OptionRangedIsize::get`]."]
#[repr(transparent)]
pub struct OptionRangedIsize<const MIN : isize, const MAX : isize>(isize);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : isize, const MAX : isize> ::core::clone::TrivialClone
for OptionRangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::clone::Clone for
OptionRangedIsize<MIN, MAX> {
#[inline]
fn clone(&self) -> OptionRangedIsize<MIN, MAX> {
let _: ::core::clone::AssertParamIsClone<isize>;
*self
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::marker::Copy for
OptionRangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Eq for
OptionRangedIsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<isize>;
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::hash::Hash for
OptionRangedIsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedIsize<0, 0> {
#[doc = "A RangedIsize that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : isize>() -> RangedIsize<VALUE, VALUE> {
unsafe { RangedIsize::new_unchecked(VALUE) }
}
}
impl<const MIN : isize, const MAX : isize> RangedIsize<MIN, MAX> {
/// The smallest value that can be represented by this type.
pub const MIN: Self = Self::new_static::<MIN>();
/// The largest value that can be represented by this type.
pub const MAX: Self = Self::new_static::<MAX>();
/// Creates a ranged integer without checking the value.
///
/// # Safety
///
/// The value must be within the range `MIN..=MAX`.
#[track_caller]
#[inline(always)]
pub const unsafe fn new_unchecked(value: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
assert_unchecked(MIN <= value && value <= MAX);
Self(Unsafe::new(value))
}
}
/// Returns the value as a primitive type.
///
/// A call to this function will output a hint to the compiler that the value is in
/// range. In general this will help the optimizer to generate better code, but in edge
/// cases this may lead to worse code generation. To avoid outputting the hint, you can
#[doc = "use [`RangedIsize::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX)
};
*self.0.get()
}
/// Returns the value as a primitive type.
///
#[doc = "The returned value is identical to [`RangedIsize::get`]."]
/// Unlike `get`, no hints are output to the compiler indicating the range that the
/// value is in. Depending on the scenario, this may with be helpful or harmful too
/// optimization.
#[inline(always)]
pub const fn get_without_hint(self) -> isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
*self.0.get()
}
#[track_caller]
#[inline(always)]
pub(crate) const fn get_ref(&self) -> &isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
let value = self.0.get();
unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
value
}
/// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
#[inline(always)]
pub const fn new(value: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if value < MIN || value > MAX {
None
} else { Some(unsafe { Self::new_unchecked(value) }) }
}
/// Creates a ranged integer with a statically known value. **Fails to compile** if the
/// value is not in range.
#[inline(always)]
pub const fn new_static<const VALUE : isize>() -> Self {
const {
if !(MIN <= VALUE) {
::core::panicking::panic("assertion failed: MIN <= VALUE")
};
if !(VALUE <= MAX) {
::core::panicking::panic("assertion failed: VALUE <= MAX")
};
}
unsafe { Self::new_unchecked(VALUE) }
}
/// Creates a ranged integer with the given value, saturating if it is out of range.
#[inline]
pub const fn new_saturating(value: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if value < MIN {
Self::MIN
} else if value > MAX {
Self::MAX
} else { unsafe { Self::new_unchecked(value) } }
}
/// Emit a hint to the compiler that the value is in range.
///
/// In some situations, this can help the optimizer to generate better code. In edge
/// cases this may lead to **worse** code generation. If you are unsure whether this is
/// helpful, harmful, or neutral, you should use [`cargo-show-asm`] to compare the
/// generated assembly.
///
/// Aside from potentially affecting optimization, this function is a no-op.
///
/// [`cargo-show-asm`]: https://crates.io/crates/cargo-show-asm
#[inline(always)]
pub const fn emit_range_hint(self) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
let value = self.0.get();
unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
}
/// Expand the range that the value may be in. **Fails to compile** if the new range is
/// not a superset of the current range.
#[inline(always)]
pub const fn expand<const NEW_MIN : isize, const NEW_MAX : isize>(self)
-> RangedIsize<NEW_MIN, NEW_MAX> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
if !(NEW_MIN <= NEW_MAX) {
::core::panicking::panic("assertion failed: NEW_MIN <= NEW_MAX")
};
if !(NEW_MIN <= MIN) {
::core::panicking::panic("assertion failed: NEW_MIN <= MIN")
};
if !(NEW_MAX >= MAX) {
::core::panicking::panic("assertion failed: NEW_MAX >= MAX")
};
}
unsafe { RangedIsize::new_unchecked(self.get()) }
}
/// Attempt to narrow the range that the value may be in. Returns `None` if the value
/// is outside the new range. **Fails to compile** if the new range is not a subset of
/// the current range.
#[inline(always)]
pub const fn narrow<const NEW_MIN : isize, const NEW_MAX : isize>(self)
-> Option<RangedIsize<NEW_MIN, NEW_MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
if !(NEW_MIN <= NEW_MAX) {
::core::panicking::panic("assertion failed: NEW_MIN <= NEW_MAX")
};
if !(NEW_MIN >= MIN) {
::core::panicking::panic("assertion failed: NEW_MIN >= MIN")
};
if !(NEW_MAX <= MAX) {
::core::panicking::panic("assertion failed: NEW_MAX <= MAX")
};
}
RangedIsize::<NEW_MIN, NEW_MAX>::new(self.get())
}
/// Converts a string slice in a given base to an integer.
///
/// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
/// and trailing whitespace represent an error. Digits are a subset of these characters,
/// depending on `radix`:
///
/// - `0-9`
/// - `a-z`
/// - `A-Z`
///
/// # Panics
///
/// Panics if `radix` is not in the range `2..=36`.
///
/// # Examples
///
/// Basic usage:
///
/// ```rust
#[doc = "# use deranged::RangedIsize;"]
#[doc =
"assert_eq!(RangedIsize::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedIsize::new_static::<10>()));"]
/// ```
#[inline]
pub fn from_str_radix(src: &str, radix: u32)
-> Result<Self, ParseIntError> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
match isize::from_str_radix(src, radix) {
Ok(value) if value > MAX => {
Err(ParseIntError { kind: IntErrorKind::PosOverflow })
}
Ok(value) if value < MIN => {
Err(ParseIntError { kind: IntErrorKind::NegOverflow })
}
Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
}
}
/// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
/// value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_add(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_add(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
/// range.
///
/// # Safety
///
/// The result of `self + rhs` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_add(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_add(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_add(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
/// value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_sub(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_sub(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
/// range.
///
/// # Safety
///
/// The result of `self - rhs` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_sub(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_sub(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_sub(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
/// value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_mul(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_mul(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
/// in range.
///
/// # Safety
///
/// The result of `self * rhs` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_mul(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_mul(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_mul(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
/// if the resulting value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_div(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_div(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
/// the result is in range.
///
/// # Safety
///
/// `self` must not be zero and the result of `self / rhs` must be in the range
/// `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_div(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_div(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_div(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
/// `rhs == 0` or if the resulting value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_div_euclid(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_div_euclid(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
/// `rhs != 0` and that the result is in range.
///
/// # Safety
///
/// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
/// range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_div_euclid(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_div_euclid(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_div_euclid(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
/// if the resulting value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_rem(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_rem(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
/// result is in range.
///
/// # Safety
///
/// `self` must not be zero and the result of `self % rhs` must be in the range
/// `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_rem(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_rem(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_rem(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
/// `rhs == 0` or if the resulting value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_rem_euclid(self, rhs: isize) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_rem_euclid(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
/// `rhs != 0` and that the result is in range.
///
/// # Safety
///
/// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
/// range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_rem_euclid(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_rem_euclid(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_rem_euclid(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked negation. Computes `-self`, returning `None` if the resulting value is out
/// of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_neg(self) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_neg() {
Some(value) => value,
None => return None,
})
}
/// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
///
/// # Safety
///
/// The result of `-self` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_neg(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_neg();
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_neg() {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Negation. Computes `self.neg()`, **failing to compile** if the result is not
/// guaranteed to be in range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline(always)]
pub const fn neg(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
if !(MIN != isize::MIN) {
::core::panicking::panic("assertion failed: MIN != isize::MIN")
};
if !(-MIN <= MAX) {
::core::panicking::panic("assertion failed: -MIN <= MAX")
};
if !(-MAX >= MIN) {
::core::panicking::panic("assertion failed: -MAX >= MIN")
};
}
unsafe { self.unchecked_neg() }
}
/// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
/// is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_shl(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
///
/// # Safety
///
/// The result of `self << rhs` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_shl(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_shl(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Checked shift right. Computes `self >> rhs`, returning `None` if
/// the resulting value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_shr(rhs) {
Some(value) => value,
None => return None,
})
}
/// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
///
/// # Safety
///
/// The result of `self >> rhs` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_shr(rhs);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_shr(rhs) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
#[doc =
r" Checked absolute value. Computes `self.abs()`, returning `None` if the resulting"]
#[doc = r" value is out of range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_abs(self) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_abs() {
Some(value) => value,
None => return None,
})
}
#[doc =
r" Unchecked absolute value. Computes `self.abs()`, assuming that the result is in"]
#[doc = r" range."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc = r" The result of `self.abs()` must be in the range `MIN..=MAX`."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_abs(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_abs();
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_abs() {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
#[doc =
r" Absolute value. Computes `self.abs()`, **failing to compile** if the result is not"]
#[doc = r" guaranteed to be in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline(always)]
pub const fn abs(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
if !(MIN != isize::MIN) {
::core::panicking::panic("assertion failed: MIN != isize::MIN")
};
if !(-MIN <= MAX) {
::core::panicking::panic("assertion failed: -MIN <= MAX")
};
}
unsafe { self.unchecked_abs() }
}
/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
/// value is out of range.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn checked_pow(self, exp: u32) -> Option<Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(match self.get().checked_pow(exp) {
Some(value) => value,
None => return None,
})
}
/// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
/// range.
///
/// # Safety
///
/// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline(always)]
pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked({
let opt = self.get().checked_pow(exp);
if true {
if !opt.is_some() {
::core::panicking::panic("assertion failed: opt.is_some()")
};
};
match self.get().checked_pow(exp) {
Some(value) => value,
None => core::hint::unreachable_unchecked(),
}
})
}
}
/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
/// bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_add(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_add(rhs))
}
/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
/// bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_sub(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
#[doc =
r" Saturating integer negation. Computes `self - rhs`, saturating at the numeric"]
#[doc = r" bounds."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_neg(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_neg())
}
#[doc =
r" Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_abs(self) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_abs())
}
/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
/// bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_mul(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_mul(rhs))
}
/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
/// numeric bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn saturating_pow(self, exp: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_pow(exp))
}
#[doc =
r" Returns `true` if the number is positive and `false` if the number is zero or"]
#[doc = r" negative."]
#[inline]
pub const fn is_positive(self) -> bool {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().is_positive()
}
#[doc =
r" Returns `true` if the number is negative and `false` if the number is zero or"]
#[doc = r" positive."]
#[inline]
pub const fn is_negative(self) -> bool {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().is_negative()
}
/// Compute the `rem_euclid` of this type with its unsigned type equivalent
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
#[allow(trivial_numeric_casts)]
const fn rem_euclid_unsigned(rhs: isize, range_len: usize) -> usize {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as usize) % range_len
} else {
let rhs_abs = (isize::wrapping_sub(0, rhs)) as usize;
(((usize::MAX / range_len) * range_len) - (rhs_abs)) % range_len
}
}
/// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
/// bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
#[allow(trivial_numeric_casts)]
pub const fn wrapping_add(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == isize::MIN && MAX == isize::MAX {
return unsafe {
Self::new_unchecked(self.get().wrapping_add(rhs))
}
}
let inner = self.get();
let range_len = MAX.abs_diff(MIN) + 1;
let offset = Self::rem_euclid_unsigned(rhs, range_len);
let greater_vals = MAX.abs_diff(inner);
if offset <= greater_vals {
unsafe {
Self::new_unchecked(((inner as usize).wrapping_add(offset)) as
isize)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
usize).wrapping_add(offset - (greater_vals + 1))) as isize)
}
}
}
/// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
/// bounds.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
#[allow(trivial_numeric_casts)]
pub const fn wrapping_sub(self, rhs: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == isize::MIN && MAX == isize::MAX {
return unsafe {
Self::new_unchecked(self.get().wrapping_sub(rhs))
}
}
let inner = self.get();
let range_len = MAX.abs_diff(MIN) + 1;
let offset = Self::rem_euclid_unsigned(rhs, range_len);
let lesser_vals = MIN.abs_diff(inner);
if offset <= lesser_vals {
unsafe {
Self::new_unchecked(((inner as usize).wrapping_sub(offset)) as
isize)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
usize).wrapping_sub(offset - (lesser_vals + 1))) as isize)
}
}
}
}
impl<const MIN : isize, const MAX : isize> OptionRangedIsize<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: isize =
match (MIN, MAX) {
(isize::MIN, isize::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(isize::MIN, _) => isize::MAX,
(_, _) => isize::MIN,
};
/// An optional ranged value that is not present.
#[allow(non_upper_case_globals)]
pub const None: Self = Self(Self::NICHE);
/// Creates an optional ranged value that is present.
#[allow(non_snake_case)]
#[inline(always)]
pub const fn Some(value: RangedIsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self(value.get())
}
/// Returns the value as the standard library's [`Option`] type.
#[inline(always)]
pub const fn get(self) -> Option<RangedIsize<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedIsize::new_unchecked(self.0) }) }
}
/// Creates an optional ranged integer without checking the value.
///
/// # Safety
///
/// The value must be within the range `MIN..=MAX`. As the value used for niche
/// value optimization is unspecified, the provided value must not be the niche
/// value.
#[inline(always)]
#[track_caller]
pub const unsafe fn some_unchecked(value: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { assert_unchecked(MIN <= value && value <= MAX) };
Self(value)
}
/// Obtain the inner value of the struct. This is useful for comparisons.
#[inline(always)]
pub(crate) const fn inner(self) -> isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.0
}
/// Obtain the value of the struct as an `Option` of the primitive type.
///
/// A call to this function will output a hint to the compiler that the value is in
/// range. In general this will help the optimizer to generate better code, but in edge
/// cases this may lead to worse code generation. To avoid outputting the hint, you can
#[doc = "use [`OptionRangedIsize::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<isize> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Some(match self.get() {
Some(value) => value,
None => return None,
}.get())
}
/// Obtain the value of the struct as an `Option` of the primitive type.
///
#[doc =
"The returned value is identical to [`OptionRangedIsize::get_primitive`]."]
/// Unlike `get_primitive`, no hints are output to the compiler indicating the range
/// that the value is in. Depending on the scenario, this may with be helpful or harmful
/// too optimization.
#[inline(always)]
pub const fn get_primitive_without_hint(self) -> Option<isize> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Some(match self.get() {
Some(value) => value,
None => return None,
}.get_without_hint())
}
/// Returns `true` if the value is the niche value.
#[inline(always)]
pub const fn is_none(&self) -> bool {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().is_none()
}
/// Returns `true` if the value is not the niche value.
#[inline(always)]
pub const fn is_some(&self) -> bool {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().is_some()
}
}
impl<const MIN : isize, const MAX : isize> fmt::Debug for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::Debug for
OptionRangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::Display for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> smart_display::SmartDisplay for
RangedIsize<MIN, MAX> {
type Metadata = <isize as smart_display::SmartDisplay>::Metadata;
#[inline(always)]
fn metadata(&self, f: smart_display::FormatterOptions)
-> smart_display::Metadata<'_, Self> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get_ref().metadata(f).reuse()
}
#[inline(always)]
fn fmt_with_metadata(&self, f: &mut fmt::Formatter<'_>,
metadata: smart_display::Metadata<'_, Self>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt_with_metadata(f, metadata.reuse())
}
}
impl<const MIN : isize, const MAX : isize> Default for
OptionRangedIsize<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : isize, const MAX : isize> AsRef<isize> for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : isize, const MAX : isize> Borrow<isize> for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : isize, const MAX_A : isize, const MIN_B : isize, const
MAX_B : isize> PartialEq<RangedIsize<MIN_B, MAX_B>> for
RangedIsize<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedIsize<MIN_B, MAX_B>) -> bool {
const {
if !(MIN_A <= MAX_A) {
::core::panicking::panic("assertion failed: MIN_A <= MAX_A")
};
if !(MIN_B <= MAX_B) {
::core::panicking::panic("assertion failed: MIN_B <= MAX_B")
};
}
self.get() == other.get()
}
}
impl<const MIN_A : isize, const MAX_A : isize, const MIN_B : isize, const
MAX_B : isize> PartialEq<OptionRangedIsize<MIN_B, MAX_B>> for
OptionRangedIsize<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedIsize<MIN_B, MAX_B>) -> bool {
const {
if !(MIN_A <= MAX_A) {
::core::panicking::panic("assertion failed: MIN_A <= MAX_A")
};
if !(MIN_B <= MAX_B) {
::core::panicking::panic("assertion failed: MIN_B <= MAX_B")
};
}
self.inner() == other.inner()
}
}
impl<const MIN_A : isize, const MAX_A : isize, const MIN_B : isize, const
MAX_B : isize> PartialOrd<RangedIsize<MIN_B, MAX_B>> for
RangedIsize<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedIsize<MIN_B, MAX_B>)
-> Option<Ordering> {
const {
if !(MIN_A <= MAX_A) {
::core::panicking::panic("assertion failed: MIN_A <= MAX_A")
};
if !(MIN_B <= MAX_B) {
::core::panicking::panic("assertion failed: MIN_B <= MAX_B")
};
}
self.get().partial_cmp(&other.get())
}
}
impl<const MIN_A : isize, const MAX_A : isize, const MIN_B : isize, const
MAX_B : isize> PartialOrd<OptionRangedIsize<MIN_B, MAX_B>> for
OptionRangedIsize<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedIsize<MIN_B, MAX_B>)
-> Option<Ordering> {
const {
if !(MIN_A <= MAX_A) {
::core::panicking::panic("assertion failed: MIN_A <= MAX_A")
};
if !(MIN_B <= MAX_B) {
::core::panicking::panic("assertion failed: MIN_B <= MAX_B")
};
}
if self.is_none() && other.is_none() {
Some(Ordering::Equal)
} else if self.is_none() {
Some(Ordering::Less)
} else if other.is_none() {
Some(Ordering::Greater)
} else { self.inner().partial_cmp(&other.inner()) }
}
}
impl<const MIN : isize, const MAX : isize> Ord for OptionRangedIsize<MIN, MAX>
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.is_none() && other.is_none() {
Ordering::Equal
} else if self.is_none() {
Ordering::Less
} else if other.is_none() {
Ordering::Greater
} else { self.inner().cmp(&other.inner()) }
}
}
impl<const MIN : isize, const MAX : isize> fmt::Binary for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::LowerHex for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::UpperHex for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::LowerExp for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::UpperExp for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> fmt::Octal for
RangedIsize<MIN, MAX> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
self.get().fmt(f)
}
}
impl<const MIN : isize, const MAX : isize> From<RangedIsize<MIN, MAX>> for
isize {
#[inline(always)]
fn from(value: RangedIsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : isize, const MAX : isize> From<RangedIsize<MIN, MAX>> for
OptionRangedIsize<MIN, MAX> {
#[inline(always)]
fn from(value: RangedIsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : isize, const MAX : isize> From<Option<RangedIsize<MIN, MAX>>>
for OptionRangedIsize<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedIsize<MIN, MAX>>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
match value { Some(value) => Self::Some(value), None => Self::None, }
}
}
impl<const MIN : isize, const MAX : isize> From<OptionRangedIsize<MIN, MAX>>
for Option<RangedIsize<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedIsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : isize, const MAX : isize> TryFrom<isize> for
RangedIsize<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: isize) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : isize, const MAX : isize> FromStr for RangedIsize<MIN, MAX> {
type Err = ParseIntError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
let value =
s.parse::<isize>().map_err(|e|
ParseIntError { kind: e.kind().clone() })?;
if value < MIN {
Err(ParseIntError { kind: IntErrorKind::NegOverflow })
} else if value > MAX {
Err(ParseIntError { kind: IntErrorKind::PosOverflow })
} else { Ok(unsafe { Self::new_unchecked(value) }) }
}
}
impl<const MIN_SRC : u8, const MAX_SRC : u8, const MIN_DST : isize, const
MAX_DST : isize> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedU8<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (u8::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : isize, const
MAX_DST : isize> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedU16<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (u16::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : isize, const
MAX_DST : isize> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedU32<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (u32::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : isize, const
MAX_DST : isize> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedU64<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (u64::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : isize, const
MAX_DST : isize> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedU128<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (u128::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : isize,
const MAX_DST : isize> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedUsize<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (usize::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : isize, const
MAX_DST : isize> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedI8<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (i8::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : isize, const
MAX_DST : isize> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedI16<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (i16::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : isize, const
MAX_DST : isize> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedI32<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (i32::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : isize, const
MAX_DST : isize> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedI64<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (i64::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : isize, const
MAX_DST : isize> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedIsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedI128<MIN_SRC, MAX_SRC>) -> Self {
const {
if !(MIN_SRC <= MAX_SRC) {
{
::core::panicking::panic_fmt(format_args!("source range is invalid"));
}
};
if !(MIN_DST <= MAX_DST) {
{
::core::panicking::panic_fmt(format_args!("target range is invalid"));
}
};
match (i128::MIN == 0, isize::MIN == 0) {
(true, true) => {
if !(MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, false) => {
if !(MIN_SRC as i128 >= MIN_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(true, false) => {
if !(MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_DST >= 0 && MAX_SRC as u128 <= i128::MAX as u128 &&
MAX_SRC as i128 <= MAX_DST as i128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
(false, true) => {
if !(MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("minimum value cannot be represented in the target range"));
}
};
if !(MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128) {
{
::core::panicking::panic_fmt(format_args!("maximum value cannot be represented in the target range"));
}
};
}
}
}
unsafe { RangedIsize::new_unchecked(value.get() as isize) }
}
}impl_ranged! {
1692RangedU8 {
1693 mod_name: ranged_u8
1694 internal: u8
1695 signed: false
1696unsigned: u8
1697 optional: OptionRangedU81698 from: [
1699RangedU16(u16)
1700RangedU32(u32)
1701RangedU64(u64)
1702RangedU128(u128)
1703RangedUsize(usize)
1704RangedI8(i8)
1705RangedI16(i16)
1706RangedI32(i32)
1707RangedI64(i64)
1708RangedI128(i128)
1709RangedIsize(isize)
1710 ]
1711 }
1712RangedU16 {
1713 mod_name: ranged_u16
1714 internal: u16
1715 signed: false
1716unsigned: u16
1717 optional: OptionRangedU161718 from: [
1719RangedU8(u8)
1720RangedU32(u32)
1721RangedU64(u64)
1722RangedU128(u128)
1723RangedUsize(usize)
1724RangedI8(i8)
1725RangedI16(i16)
1726RangedI32(i32)
1727RangedI64(i64)
1728RangedI128(i128)
1729RangedIsize(isize)
1730 ]
1731 }
1732RangedU32 {
1733 mod_name: ranged_u32
1734 internal: u32
1735 signed: false
1736unsigned: u32
1737 optional: OptionRangedU321738 from: [
1739RangedU8(u8)
1740RangedU16(u16)
1741RangedU64(u64)
1742RangedU128(u128)
1743RangedUsize(usize)
1744RangedI8(i8)
1745RangedI16(i16)
1746RangedI32(i32)
1747RangedI64(i64)
1748RangedI128(i128)
1749RangedIsize(isize)
1750 ]
1751 }
1752RangedU64 {
1753 mod_name: ranged_u64
1754 internal: u64
1755 signed: false
1756unsigned: u64
1757 optional: OptionRangedU641758 from: [
1759RangedU8(u8)
1760RangedU16(u16)
1761RangedU32(u32)
1762RangedU128(u128)
1763RangedUsize(usize)
1764RangedI8(i8)
1765RangedI16(i16)
1766RangedI32(i32)
1767RangedI64(i64)
1768RangedI128(i128)
1769RangedIsize(isize)
1770 ]
1771 }
1772RangedU128 {
1773 mod_name: ranged_u128
1774 internal: u128
1775 signed: false
1776unsigned: u128
1777 optional: OptionRangedU1281778 from: [
1779RangedU8(u8)
1780RangedU16(u16)
1781RangedU32(u32)
1782RangedU64(u64)
1783RangedUsize(usize)
1784RangedI8(i8)
1785RangedI16(i16)
1786RangedI32(i32)
1787RangedI64(i64)
1788RangedI128(i128)
1789RangedIsize(isize)
1790 ]
1791 }
1792RangedUsize {
1793 mod_name: ranged_usize
1794 internal: usize
1795 signed: false
1796unsigned: usize
1797 optional: OptionRangedUsize1798 from: [
1799RangedU8(u8)
1800RangedU16(u16)
1801RangedU32(u32)
1802RangedU64(u64)
1803RangedU128(u128)
1804RangedI8(i8)
1805RangedI16(i16)
1806RangedI32(i32)
1807RangedI64(i64)
1808RangedI128(i128)
1809RangedIsize(isize)
1810 ]
1811 manual: [rand_09]
1812 }
1813RangedI8 {
1814 mod_name: ranged_i8
1815 internal: i8
1816 signed: true
1817unsigned: u8
1818 optional: OptionRangedI81819 from: [
1820RangedU8(u8)
1821RangedU16(u16)
1822RangedU32(u32)
1823RangedU64(u64)
1824RangedU128(u128)
1825RangedUsize(usize)
1826RangedI16(i16)
1827RangedI32(i32)
1828RangedI64(i64)
1829RangedI128(i128)
1830RangedIsize(isize)
1831 ]
1832 }
1833RangedI16 {
1834 mod_name: ranged_i16
1835 internal: i16
1836 signed: true
1837unsigned: u16
1838 optional: OptionRangedI161839 from: [
1840RangedU8(u8)
1841RangedU16(u16)
1842RangedU32(u32)
1843RangedU64(u64)
1844RangedU128(u128)
1845RangedUsize(usize)
1846RangedI8(i8)
1847RangedI32(i32)
1848RangedI64(i64)
1849RangedI128(i128)
1850RangedIsize(isize)
1851 ]
1852 }
1853RangedI32 {
1854 mod_name: ranged_i32
1855 internal: i32
1856 signed: true
1857unsigned: u32
1858 optional: OptionRangedI321859 from: [
1860RangedU8(u8)
1861RangedU16(u16)
1862RangedU32(u32)
1863RangedU64(u64)
1864RangedU128(u128)
1865RangedUsize(usize)
1866RangedI8(i8)
1867RangedI16(i16)
1868RangedI64(i64)
1869RangedI128(i128)
1870RangedIsize(isize)
1871 ]
1872 }
1873RangedI64 {
1874 mod_name: ranged_i64
1875 internal: i64
1876 signed: true
1877unsigned: u64
1878 optional: OptionRangedI641879 from: [
1880RangedU8(u8)
1881RangedU16(u16)
1882RangedU32(u32)
1883RangedU64(u64)
1884RangedU128(u128)
1885RangedUsize(usize)
1886RangedI8(i8)
1887RangedI16(i16)
1888RangedI32(i32)
1889RangedI128(i128)
1890RangedIsize(isize)
1891 ]
1892 }
1893RangedI128 {
1894 mod_name: ranged_i128
1895 internal: i128
1896 signed: true
1897unsigned: u128
1898 optional: OptionRangedI1281899 from: [
1900RangedU8(u8)
1901RangedU16(u16)
1902RangedU32(u32)
1903RangedU64(u64)
1904RangedU128(u128)
1905RangedUsize(usize)
1906RangedI8(i8)
1907RangedI16(i16)
1908RangedI32(i32)
1909RangedI64(i64)
1910RangedIsize(isize)
1911 ]
1912 }
1913RangedIsize {
1914 mod_name: ranged_isize
1915 internal: isize
1916 signed: true
1917unsigned: usize
1918 optional: OptionRangedIsize1919 from: [
1920RangedU8(u8)
1921RangedU16(u16)
1922RangedU32(u32)
1923RangedU64(u64)
1924RangedU128(u128)
1925RangedUsize(usize)
1926RangedI8(i8)
1927RangedI16(i16)
1928RangedI32(i32)
1929RangedI64(i64)
1930RangedI128(i128)
1931 ]
1932 manual: [rand_09]
1933 }
1934}19351936#[cfg(feature = "rand09")]
1937impl<const MIN: usize, const MAX: usize> rand09::distr::Distribution<RangedUsize<MIN, MAX>>
1938for rand09::distr::StandardUniform
1939{
1940#[inline]
1941fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
1942const {
1943assert!(MIN <= MAX);
1944 }
19451946#[cfg(target_pointer_width = "16")]
1947let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
1948#[cfg(target_pointer_width = "32")]
1949let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
1950#[cfg(target_pointer_width = "64")]
1951let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
1952#[cfg(not(any(
1953 target_pointer_width = "16",
1954 target_pointer_width = "32",
1955 target_pointer_width = "64"
1956)))]
1957compile_error("platform has unusual (and unsupported) pointer width");
19581959 RangedUsize::new(value).expect("rand failed to generate a valid value")
1960 }
1961}
19621963#[cfg(feature = "rand09")]
1964impl<const MIN: isize, const MAX: isize> rand09::distr::Distribution<RangedIsize<MIN, MAX>>
1965for rand09::distr::StandardUniform
1966{
1967#[inline]
1968fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
1969const {
1970assert!(MIN <= MAX);
1971 }
19721973#[cfg(target_pointer_width = "16")]
1974let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
1975#[cfg(target_pointer_width = "32")]
1976let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
1977#[cfg(target_pointer_width = "64")]
1978let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
1979#[cfg(not(any(
1980 target_pointer_width = "16",
1981 target_pointer_width = "32",
1982 target_pointer_width = "64"
1983)))]
1984compile_error("platform has unusual (and unsupported) pointer width");
19851986 RangedIsize::new(value).expect("rand failed to generate a valid value")
1987 }
1988}