1//! `deranged` is a proof-of-concept implementation of ranged integers.
23#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide))]
4#![no_std]
5#![doc(test(attr(deny(warnings))))]
6#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))]
78#[cfg(all(feature = "alloc", any(feature = "serde", feature = "quickcheck")))]
9extern crate alloc;
1011#[cfg(test)]
12mod tests;
13mod unsafe_wrapper;
1415use core::borrow::Borrow;
16use core::cmp::Ordering;
17use core::error::Error;
18use core::fmt;
19use core::hint::assert_unchecked;
20use core::num::{IntErrorKind, NonZero};
21use core::str::FromStr;
2223/// A macro to define a ranged integer with an automatically computed inner type.
24///
25/// The minimum and maximum values are provided as integer literals, and the macro will compute an
26/// appropriate inner type to represent the range. This will be the smallest integer type that can
27/// store both the minimum and maximum values, with a preference for unsigned types if both are
28/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
29/// to either or both of the minimum and maximum values, respectively.
30///
31/// # Examples
32///
33/// ```rust,ignore
34/// int!(0, 100); // RangedU8<0, 100>
35/// int!(0i, 100); // RangedI8<0, 100>
36/// int!(-5, 5); // RangedI8<-5, 5>
37/// int!(-5u, 5); // compile error (-5 cannot be unsigned)
38/// ```
39#[cfg(all(docsrs, feature = "macros"))]
40#[macro_export]
41macro_rules! int {
42 ($min:literal, $max:literal) => {};
43}
4445/// A macro to define an optional ranged integer with an automatically computed inner type.
46///
47/// The minimum and maximum values are provided as integer literals, and the macro will compute an
48/// appropriate inner type to represent the range. This will be the smallest integer type that can
49/// store both the minimum and maximum values, with a preference for unsigned types if both are
50/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
51/// to either or both of the minimum and maximum values, respectively.
52///
53/// # Examples
54///
55/// ```rust,ignore
56/// opt_int!(0, 100); // OptionRangedU8<0, 100>
57/// opt_int!(0i, 100); // OptionRangedI8<0, 100>
58/// opt_int!(-5, 5); // OptionRangedI8<-5, 5>
59/// opt_int!(-5u, 5); // compile error (-5 cannot be unsigned)
60/// ```
61#[cfg(all(docsrs, feature = "macros"))]
62#[macro_export]
63macro_rules! opt_int {
64 ($min:literal, $max:literal) => {};
65}
6667#[cfg(all(not(docsrs), feature = "macros"))]
68pub use deranged_macros::int;
69#[cfg(all(not(docsrs), feature = "macros"))]
70pub use deranged_macros::opt_int;
71#[cfg(feature = "powerfmt")]
72use powerfmt::smart_display;
7374use crate::unsafe_wrapper::Unsafe;
7576/// The error type returned when a checked integral type conversion fails.
77#[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)]
78pub struct TryFromIntError;
7980impl fmt::Displayfor TryFromIntError {
81#[inline]
82fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83f.write_str("out of range integral type conversion attempted")
84 }
85}
86impl Errorfor TryFromIntError {}
8788/// An error which can be returned when parsing an integer.
89///
90/// This error is used as the error type for the `from_str_radix()` functions on ranged integer
91/// types, such as [`RangedI8::from_str_radix`].
92///
93/// # Potential causes
94///
95/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
96/// in the string e.g., when it is obtained from the standard input.
97/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
98///
99/// # Example
100///
101/// ```rust
102/// # use deranged::RangedI32;
103/// if let Err(e) = RangedI32::<0, 10>::from_str_radix("a12", 10) {
104/// println!("Failed conversion to RangedI32: {e}");
105/// }
106/// ```
107#[allow(missing_copy_implementations)] // same as `std`
108#[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)]
109pub struct ParseIntError {
110#[allow(clippy::missing_docs_in_private_items)]
111kind: IntErrorKind,
112}
113114impl ParseIntError {
115/// Outputs the detailed cause of parsing an integer failing.
116// This function is not const because the counterpart of stdlib isn't
117#[allow(clippy::missing_const_for_fn)]
118 #[inline(always)]
119pub fn kind(&self) -> &IntErrorKind {
120&self.kind
121 }
122}
123124impl fmt::Displayfor ParseIntError {
125#[inline]
126fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127match self.kind {
128 IntErrorKind::Empty => "cannot parse integer from empty string",
129 IntErrorKind::InvalidDigit => "invalid digit found in string",
130 IntErrorKind::PosOverflow => "number too large to fit in target type",
131 IntErrorKind::NegOverflow => "number too small to fit in target type",
132 IntErrorKind::Zero => "number would be zero for non-zero type",
133_ => "Unknown Int error kind",
134 }
135 .fmt(f)
136 }
137}
138139impl Errorfor ParseIntError {}
140141/// `?` for `Option` types, usable in `const` contexts.
142macro_rules! const_try_opt {
143 ($e:expr) => {
144match $e {
145Some(value) => value,
146None => return None,
147 }
148 };
149}
150151/// Output the given tokens if the type is signed, otherwise output nothing.
152macro_rules! if_signed {
153 (true $($x:tt)*) => { $($x)*};
154 (false $($x:tt)*) => {};
155}
156157/// Output the given tokens if the type is unsigned, otherwise output nothing.
158macro_rules! if_unsigned {
159 (true $($x:tt)*) => {};
160 (false $($x:tt)*) => { $($x)* };
161}
162163/// `"A"` if `true`, `"An"` if `false`.
164macro_rules! article {
165 (true) => {
166"An"
167};
168 (false) => {
169"A"
170};
171}
172173/// `Option::unwrap_unchecked`, but usable in `const` contexts.
174macro_rules! unsafe_unwrap_unchecked {
175 ($e:expr) => {{
176let opt = $e;
177debug_assert!(opt.is_some());
178match $e {
179Some(value) => value,
180None => core::hint::unreachable_unchecked(),
181 }
182 }};
183}
184185/// Output the provided code if and only if the list does not include `rand_09`.
186#[allow(unused_macro_rules)]
187macro_rules! if_not_manual_rand_09 {
188 ([rand_09 $($rest:ident)*] $($output:tt)*) => {};
189 ([] $($output:tt)*) => {
190 $($output)*
191 };
192 ([$first:ident $($rest:ident)*] $($output:tt)*) => {
193if_not_manual_rand_09!([$($rest)*] $($output)*);
194 };
195}
196197/// Implement a ranged integer type.
198macro_rules! impl_ranged {
199 ($(
200$type:ident {
201 mod_name: $mod_name:ident
202 internal: $internal:ident
203 signed: $is_signed:ident
204 unsigned: $unsigned_type:ident
205 optional: $optional_type:ident
206 from: [$($from:ident($from_internal:ident))+]
207 $(manual: [$($skips:ident)+])?
208}
209 )*) => {$(
210#[doc = concat!(
211article!($is_signed),
212" `",
213stringify!($internal),
214"` that is known to be in the range `MIN..=MAX`.",
215 )]
216 #[repr(transparent)]
217 #[derive(Clone, Copy, Eq, Ord, Hash)]
218pub struct $type<const MIN: $internal, const MAX: $internal>(
219Unsafe<$internal>,
220 );
221222#[doc = concat!(
223"An optional `",
224stringify!($type),
225"`; similar to `Option<",
226stringify!($type),
227">` with better optimization.",
228 )]
229///
230#[doc = concat!(
231"If `MIN` is [`",
232stringify!($internal),
233"::MIN`] _and_ `MAX` is [`",
234stringify!($internal)
235 ,"::MAX`] then compilation will fail. This is because there is no way to represent \
236 the niche value.",
237 )]
238///
239 /// This type is useful when you need to store an optional ranged value in a struct, but
240 /// do not want the overhead of an `Option` type. This reduces the size of the struct
241 /// overall, and is particularly useful when you have a large number of optional fields.
242 /// Note that most operations must still be performed on the [`Option`] type, which is
243#[doc = concat!("obtained with [`", stringify!($optional_type), "::get`].")]
244 #[repr(transparent)]
245 #[derive(Clone, Copy, Eq, Hash)]
246pub struct $optional_type<const MIN: $internal, const MAX: $internal>(
247$internal,
248 );
249250impl $type<0, 0> {
251#[doc = concat!("A ", stringify!($type), " that is always `VALUE`.")]
252 #[inline(always)]
253pub const fn exact<const VALUE: $internal>() -> $type<VALUE, VALUE> {
254// Safety: The value is the only one in range.
255unsafe { $type::new_unchecked(VALUE) }
256 }
257 }
258259if_unsigned! { $is_signed
260impl $type<1, { $internal::MAX }> {
261/// Creates a ranged integer from a non-zero value.
262#[inline(always)]
263pub const fn from_nonzero(value: NonZero<$internal>) -> Self {
264// Safety: The value is non-zero, so it is in range.
265unsafe { Self::new_unchecked(value.get()) }
266 }
267268/// Creates a non-zero value from a ranged integer.
269#[inline(always)]
270pub const fn to_nonzero(self) -> NonZero<$internal> {
271// Safety: The value is in range, so it is non-zero.
272unsafe { NonZero::new_unchecked(self.get()) }
273 }
274 }}
275276impl<const MIN: $internal, const MAX: $internal> $type<MIN, MAX> {
277/// The smallest value that can be represented by this type.
278// Safety: `MIN` is in range by definition.
279pub const MIN: Self = Self::new_static::<MIN>();
280281/// The largest value that can be represented by this type.
282// Safety: `MAX` is in range by definition.
283pub const MAX: Self = Self::new_static::<MAX>();
284285/// Creates a ranged integer without checking the value.
286 ///
287 /// # Safety
288 ///
289 /// The value must be within the range `MIN..=MAX`.
290#[track_caller]
291 #[inline(always)]
292pub const unsafe fn new_unchecked(value: $internal) -> Self {
293const { assert!(MIN <= MAX); }
294// Safety: The caller must ensure that the value is in range.
295unsafe {
296 assert_unchecked(MIN <= value && value <= MAX);
297Self(Unsafe::new(value))
298 }
299 }
300301/// Returns the value as a primitive type.
302 ///
303 /// A call to this function will output a hint to the compiler that the value is in
304 /// range. In general this will help the optimizer to generate better code, but in edge
305 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
306#[doc = concat!("use [`", stringify!($type), "::get_without_hint`].")]
307 #[track_caller]
308 #[inline(always)]
309pub const fn get(self) -> $internal {
310const { assert!(MIN <= MAX); }
311// Safety: A stored value is always in range.
312unsafe { assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX) };
313*self.0.get()
314 }
315316/// Returns the value as a primitive type.
317 ///
318#[doc = concat!("The returned value is identical to [`", stringify!($type), "::get`].")]
319/// Unlike `get`, no hints are output to the compiler indicating the range that the
320 /// value is in. Depending on the scenario, this may with be helpful or harmful too
321 /// optimization.
322#[inline(always)]
323pub const fn get_without_hint(self) -> $internal {
324const { assert!(MIN <= MAX); }
325*self.0.get()
326 }
327328#[track_caller]
329 #[inline(always)]
330pub(crate) const fn get_ref(&self) -> &$internal {
331const { assert!(MIN <= MAX); }
332let value = self.0.get();
333// Safety: A stored value is always in range.
334unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
335 value
336 }
337338/// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
339#[inline(always)]
340pub const fn new(value: $internal) -> Option<Self> {
341const { assert!(MIN <= MAX); }
342if value < MIN || value > MAX {
343None
344} else {
345// Safety: The value is in range.
346Some(unsafe { Self::new_unchecked(value) })
347 }
348 }
349350/// Creates a ranged integer with a statically known value. **Fails to compile** if the
351 /// value is not in range.
352#[inline(always)]
353pub const fn new_static<const VALUE: $internal>() -> Self {
354const {
355assert!(MIN <= VALUE);
356assert!(VALUE <= MAX);
357 }
358// Safety: The value is in range.
359unsafe { Self::new_unchecked(VALUE) }
360 }
361362/// Creates a ranged integer with the given value, saturating if it is out of range.
363#[inline]
364pub const fn new_saturating(value: $internal) -> Self {
365const { assert!(MIN <= MAX); }
366if value < MIN {
367Self::MIN
368 } else if value > MAX {
369Self::MAX
370 } else {
371// Safety: The value is in range.
372unsafe { Self::new_unchecked(value) }
373 }
374 }
375376/// Emit a hint to the compiler that the value is in range.
377 ///
378 /// In some situations, this can help the optimizer to generate better code. In edge
379 /// cases this may lead to **worse** code generation. If you are unsure whether this is
380 /// helpful, harmful, or neutral, you should use [`cargo-show-asm`] to compare the
381 /// generated assembly.
382 ///
383 /// Aside from potentially affecting optimization, this function is a no-op.
384 ///
385 /// [`cargo-show-asm`]: https://crates.io/crates/cargo-show-asm
386#[inline(always)]
387pub const fn emit_range_hint(self) {
388const { assert!(MIN <= MAX); }
389let value = self.0.get();
390// Safety: A stored value is always in range.
391unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
392 }
393394/// Expand the range that the value may be in. **Fails to compile** if the new range is
395 /// not a superset of the current range.
396#[inline(always)]
397pub const fn expand<const NEW_MIN: $internal, const NEW_MAX: $internal>(
398self,
399 ) -> $type<NEW_MIN, NEW_MAX> {
400const {
401assert!(MIN <= MAX);
402assert!(NEW_MIN <= NEW_MAX);
403assert!(NEW_MIN <= MIN);
404assert!(NEW_MAX >= MAX);
405 }
406// Safety: The range is widened.
407unsafe { $type::new_unchecked(self.get()) }
408 }
409410/// Attempt to narrow the range that the value may be in. Returns `None` if the value
411 /// is outside the new range. **Fails to compile** if the new range is not a subset of
412 /// the current range.
413#[inline(always)]
414pub const fn narrow<
415const NEW_MIN: $internal,
416const NEW_MAX: $internal,
417 >(self) -> Option<$type<NEW_MIN, NEW_MAX>> {
418const {
419assert!(MIN <= MAX);
420assert!(NEW_MIN <= NEW_MAX);
421assert!(NEW_MIN >= MIN);
422assert!(NEW_MAX <= MAX);
423 }
424$type::<NEW_MIN, NEW_MAX>::new(self.get())
425 }
426427/// Converts a string slice in a given base to an integer.
428 ///
429 /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
430 /// and trailing whitespace represent an error. Digits are a subset of these characters,
431 /// depending on `radix`:
432 ///
433 /// - `0-9`
434 /// - `a-z`
435 /// - `A-Z`
436 ///
437 /// # Panics
438 ///
439 /// Panics if `radix` is not in the range `2..=36`.
440 ///
441 /// # Examples
442 ///
443 /// Basic usage:
444 ///
445 /// ```rust
446#[doc = concat!("# use deranged::", stringify!($type), ";")]
447 #[doc = concat!(
448"assert_eq!(",
449stringify!($type),
450"::<5, 10>::from_str_radix(\"A\", 16), Ok(",
451stringify!($type),
452"::new_static::<10>()));",
453 )]
454/// ```
455#[inline]
456pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
457const { assert!(MIN <= MAX); }
458match $internal::from_str_radix(src, radix) {
459Ok(value) if value > MAX => {
460Err(ParseIntError { kind: IntErrorKind::PosOverflow })
461 }
462Ok(value) if value < MIN => {
463Err(ParseIntError { kind: IntErrorKind::NegOverflow })
464 }
465// Safety: If the value was out of range, it would have been caught in a
466 // previous arm.
467Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
468Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
469 }
470 }
471472/// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
473 /// value is out of range.
474#[must_use = "this returns the result of the operation, without modifying the original"]
475 #[inline]
476pub const fn checked_add(self, rhs: $internal) -> Option<Self> {
477const { assert!(MIN <= MAX); }
478Self::new(const_try_opt!(self.get().checked_add(rhs)))
479 }
480481/// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
482 /// range.
483 ///
484 /// # Safety
485 ///
486 /// The result of `self + rhs` must be in the range `MIN..=MAX`.
487#[must_use = "this returns the result of the operation, without modifying the original"]
488 #[track_caller]
489 #[inline(always)]
490pub const unsafe fn unchecked_add(self, rhs: $internal) -> Self {
491const { assert!(MIN <= MAX); }
492// Safety: The caller must ensure that the result is in range.
493unsafe {
494Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_add(rhs)))
495 }
496 }
497498/// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
499 /// value is out of range.
500#[must_use = "this returns the result of the operation, without modifying the original"]
501 #[inline]
502pub const fn checked_sub(self, rhs: $internal) -> Option<Self> {
503const { assert!(MIN <= MAX); }
504Self::new(const_try_opt!(self.get().checked_sub(rhs)))
505 }
506507/// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
508 /// range.
509 ///
510 /// # Safety
511 ///
512 /// The result of `self - rhs` must be in the range `MIN..=MAX`.
513#[must_use = "this returns the result of the operation, without modifying the original"]
514 #[track_caller]
515 #[inline(always)]
516pub const unsafe fn unchecked_sub(self, rhs: $internal) -> Self {
517const { assert!(MIN <= MAX); }
518// Safety: The caller must ensure that the result is in range.
519unsafe {
520Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_sub(rhs)))
521 }
522 }
523524/// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
525 /// value is out of range.
526#[must_use = "this returns the result of the operation, without modifying the original"]
527 #[inline]
528pub const fn checked_mul(self, rhs: $internal) -> Option<Self> {
529const { assert!(MIN <= MAX); }
530Self::new(const_try_opt!(self.get().checked_mul(rhs)))
531 }
532533/// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
534 /// in range.
535 ///
536 /// # Safety
537 ///
538 /// The result of `self * rhs` must be in the range `MIN..=MAX`.
539#[must_use = "this returns the result of the operation, without modifying the original"]
540 #[track_caller]
541 #[inline(always)]
542pub const unsafe fn unchecked_mul(self, rhs: $internal) -> Self {
543const { assert!(MIN <= MAX); }
544// Safety: The caller must ensure that the result is in range.
545unsafe {
546Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_mul(rhs)))
547 }
548 }
549550/// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
551 /// if the resulting value is out of range.
552#[must_use = "this returns the result of the operation, without modifying the original"]
553 #[inline]
554pub const fn checked_div(self, rhs: $internal) -> Option<Self> {
555const { assert!(MIN <= MAX); }
556Self::new(const_try_opt!(self.get().checked_div(rhs)))
557 }
558559/// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
560 /// the result is in range.
561 ///
562 /// # Safety
563 ///
564 /// `self` must not be zero and the result of `self / rhs` must be in the range
565 /// `MIN..=MAX`.
566#[must_use = "this returns the result of the operation, without modifying the original"]
567 #[track_caller]
568 #[inline(always)]
569pub const unsafe fn unchecked_div(self, rhs: $internal) -> Self {
570const { assert!(MIN <= MAX); }
571// Safety: The caller must ensure that the result is in range and that `rhs` is not
572 // zero.
573unsafe {
574Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_div(rhs)))
575 }
576 }
577578/// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
579 /// `rhs == 0` or if the resulting value is out of range.
580#[must_use = "this returns the result of the operation, without modifying the original"]
581 #[inline]
582pub const fn checked_div_euclid(self, rhs: $internal) -> Option<Self> {
583const { assert!(MIN <= MAX); }
584Self::new(const_try_opt!(self.get().checked_div_euclid(rhs)))
585 }
586587/// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
588 /// `rhs != 0` and that the result is in range.
589 ///
590 /// # Safety
591 ///
592 /// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
593 /// range `MIN..=MAX`.
594#[must_use = "this returns the result of the operation, without modifying the original"]
595 #[track_caller]
596 #[inline(always)]
597pub const unsafe fn unchecked_div_euclid(self, rhs: $internal) -> Self {
598const { assert!(MIN <= MAX); }
599// Safety: The caller must ensure that the result is in range and that `rhs` is not
600 // zero.
601unsafe {
602Self::new_unchecked(
603unsafe_unwrap_unchecked!(self.get().checked_div_euclid(rhs))
604 )
605 }
606 }
607608if_unsigned!($is_signed
609/// Remainder. Computes `self % rhs`, statically guaranteeing that the returned value
610 /// is in range.
611#[must_use = "this returns the result of the operation, without modifying the original"]
612 #[track_caller]
613 #[inline]
614pub const fn rem<const RHS_VALUE: $internal>(
615self,
616 rhs: $type<RHS_VALUE, RHS_VALUE>,
617 ) -> $type<0, RHS_VALUE> {
618const { assert!(MIN <= MAX); }
619// Safety: The result is guaranteed to be in range due to the nature of remainder on
620 // unsigned integers.
621unsafe { $type::new_unchecked(self.get() % rhs.get()) }
622 });
623624/// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
625 /// if the resulting value is out of range.
626#[must_use = "this returns the result of the operation, without modifying the original"]
627 #[inline]
628pub const fn checked_rem(self, rhs: $internal) -> Option<Self> {
629const { assert!(MIN <= MAX); }
630Self::new(const_try_opt!(self.get().checked_rem(rhs)))
631 }
632633/// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
634 /// result is in range.
635 ///
636 /// # Safety
637 ///
638 /// `self` must not be zero and the result of `self % rhs` must be in the range
639 /// `MIN..=MAX`.
640#[must_use = "this returns the result of the operation, without modifying the original"]
641 #[track_caller]
642 #[inline(always)]
643pub const unsafe fn unchecked_rem(self, rhs: $internal) -> Self {
644const { assert!(MIN <= MAX); }
645// Safety: The caller must ensure that the result is in range and that `rhs` is not
646 // zero.
647unsafe {
648Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_rem(rhs)))
649 }
650 }
651652/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
653 /// `rhs == 0` or if the resulting value is out of range.
654#[must_use = "this returns the result of the operation, without modifying the original"]
655 #[inline]
656pub const fn checked_rem_euclid(self, rhs: $internal) -> Option<Self> {
657const { assert!(MIN <= MAX); }
658Self::new(const_try_opt!(self.get().checked_rem_euclid(rhs)))
659 }
660661/// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
662 /// `rhs != 0` and that the result is in range.
663 ///
664 /// # Safety
665 ///
666 /// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
667 /// range `MIN..=MAX`.
668#[must_use = "this returns the result of the operation, without modifying the original"]
669 #[track_caller]
670 #[inline(always)]
671pub const unsafe fn unchecked_rem_euclid(self, rhs: $internal) -> Self {
672const { assert!(MIN <= MAX); }
673// Safety: The caller must ensure that the result is in range and that `rhs` is not
674 // zero.
675unsafe {
676Self::new_unchecked(
677unsafe_unwrap_unchecked!(self.get().checked_rem_euclid(rhs))
678 )
679 }
680 }
681682/// Checked negation. Computes `-self`, returning `None` if the resulting value is out
683 /// of range.
684#[must_use = "this returns the result of the operation, without modifying the original"]
685 #[inline]
686pub const fn checked_neg(self) -> Option<Self> {
687const { assert!(MIN <= MAX); }
688Self::new(const_try_opt!(self.get().checked_neg()))
689 }
690691/// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
692 ///
693 /// # Safety
694 ///
695 /// The result of `-self` must be in the range `MIN..=MAX`.
696#[must_use = "this returns the result of the operation, without modifying the original"]
697 #[track_caller]
698 #[inline(always)]
699pub const unsafe fn unchecked_neg(self) -> Self {
700const { assert!(MIN <= MAX); }
701// Safety: The caller must ensure that the result is in range.
702unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_neg())) }
703 }
704705/// Negation. Computes `self.neg()`, **failing to compile** if the result is not
706 /// guaranteed to be in range.
707#[must_use = "this returns the result of the operation, without modifying the original"]
708 #[inline(always)]
709pub const fn neg(self) -> Self {
710const {
711assert!(MIN <= MAX);
712if_signed! { $is_signed
713assert!(MIN != $internal::MIN);
714assert!(-MIN <= MAX);
715assert!(-MAX >= MIN);
716 }
717if_unsigned! { $is_signed
718assert!(MAX == 0);
719 }
720 }
721// Safety: The compiler asserts that the result is in range.
722unsafe { self.unchecked_neg() }
723 }
724725/// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
726 /// is out of range.
727#[must_use = "this returns the result of the operation, without modifying the original"]
728 #[inline]
729pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
730const { assert!(MIN <= MAX); }
731Self::new(const_try_opt!(self.get().checked_shl(rhs)))
732 }
733734/// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
735 ///
736 /// # Safety
737 ///
738 /// The result of `self << rhs` must be in the range `MIN..=MAX`.
739#[must_use = "this returns the result of the operation, without modifying the original"]
740 #[track_caller]
741 #[inline(always)]
742pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
743const { assert!(MIN <= MAX); }
744// Safety: The caller must ensure that the result is in range.
745unsafe {
746Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shl(rhs)))
747 }
748 }
749750/// Checked shift right. Computes `self >> rhs`, returning `None` if
751 /// the resulting value is out of range.
752#[must_use = "this returns the result of the operation, without modifying the original"]
753 #[inline]
754pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
755const { assert!(MIN <= MAX); }
756Self::new(const_try_opt!(self.get().checked_shr(rhs)))
757 }
758759/// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
760 ///
761 /// # Safety
762 ///
763 /// The result of `self >> rhs` must be in the range `MIN..=MAX`.
764#[must_use = "this returns the result of the operation, without modifying the original"]
765 #[track_caller]
766 #[inline(always)]
767pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
768const { assert!(MIN <= MAX); }
769// Safety: The caller must ensure that the result is in range.
770unsafe {
771Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shr(rhs)))
772 }
773 }
774775if_signed!($is_signed
776/// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
777 /// value is out of range.
778#[must_use = "this returns the result of the operation, without modifying the original"]
779 #[inline]
780pub const fn checked_abs(self) -> Option<Self> {
781const { assert!(MIN <= MAX); }
782Self::new(const_try_opt!(self.get().checked_abs()))
783 }
784785/// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
786 /// range.
787 ///
788 /// # Safety
789 ///
790 /// The result of `self.abs()` must be in the range `MIN..=MAX`.
791#[must_use = "this returns the result of the operation, without modifying the original"]
792 #[track_caller]
793 #[inline(always)]
794pub const unsafe fn unchecked_abs(self) -> Self {
795const { assert!(MIN <= MAX); }
796// Safety: The caller must ensure that the result is in range.
797unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_abs())) }
798 }
799800/// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
801 /// guaranteed to be in range.
802#[must_use = "this returns the result of the operation, without modifying the original"]
803 #[inline(always)]
804pub const fn abs(self) -> Self {
805const {
806assert!(MIN <= MAX);
807assert!(MIN != $internal::MIN);
808assert!(-MIN <= MAX);
809 }
810// <Self as $crate::traits::AbsIsSafe>::ASSERT;
811 // Safety: The compiler asserts that the result is in range.
812unsafe { self.unchecked_abs() }
813 });
814815/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
816 /// value is out of range.
817#[must_use = "this returns the result of the operation, without modifying the original"]
818 #[inline]
819pub const fn checked_pow(self, exp: u32) -> Option<Self> {
820const { assert!(MIN <= MAX); }
821Self::new(const_try_opt!(self.get().checked_pow(exp)))
822 }
823824/// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
825 /// range.
826 ///
827 /// # Safety
828 ///
829 /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
830#[must_use = "this returns the result of the operation, without modifying the original"]
831 #[track_caller]
832 #[inline(always)]
833pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
834const { assert!(MIN <= MAX); }
835// Safety: The caller must ensure that the result is in range.
836unsafe {
837Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_pow(exp)))
838 }
839 }
840841/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
842 /// bounds.
843#[must_use = "this returns the result of the operation, without modifying the original"]
844 #[inline]
845pub const fn saturating_add(self, rhs: $internal) -> Self {
846const { assert!(MIN <= MAX); }
847Self::new_saturating(self.get().saturating_add(rhs))
848 }
849850/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
851 /// bounds.
852#[must_use = "this returns the result of the operation, without modifying the original"]
853 #[inline]
854pub const fn saturating_sub(self, rhs: $internal) -> Self {
855const { assert!(MIN <= MAX); }
856Self::new_saturating(self.get().saturating_sub(rhs))
857 }
858859if_signed!($is_signed
860/// Saturating integer negation. Computes `self - rhs`, saturating at the numeric
861 /// bounds.
862#[must_use = "this returns the result of the operation, without modifying the original"]
863 #[inline]
864pub const fn saturating_neg(self) -> Self {
865const { assert!(MIN <= MAX); }
866Self::new_saturating(self.get().saturating_neg())
867 });
868869if_signed!($is_signed
870/// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
871#[must_use = "this returns the result of the operation, without modifying the original"]
872 #[inline]
873pub const fn saturating_abs(self) -> Self {
874const { assert!(MIN <= MAX); }
875Self::new_saturating(self.get().saturating_abs())
876 });
877878/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
879 /// bounds.
880#[must_use = "this returns the result of the operation, without modifying the original"]
881 #[inline]
882pub const fn saturating_mul(self, rhs: $internal) -> Self {
883const { assert!(MIN <= MAX); }
884Self::new_saturating(self.get().saturating_mul(rhs))
885 }
886887/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
888 /// numeric bounds.
889#[must_use = "this returns the result of the operation, without modifying the original"]
890 #[inline]
891pub const fn saturating_pow(self, exp: u32) -> Self {
892const { assert!(MIN <= MAX); }
893Self::new_saturating(self.get().saturating_pow(exp))
894 }
895896if_signed! { $is_signed
897/// Returns `true` if the number is positive and `false` if the number is zero or
898 /// negative.
899#[inline]
900pub const fn is_positive(self) -> bool {
901const { assert!(MIN <= MAX); }
902self.get().is_positive()
903 }
904905/// Returns `true` if the number is negative and `false` if the number is zero or
906 /// positive.
907#[inline]
908pub const fn is_negative(self) -> bool {
909const { assert!(MIN <= MAX); }
910self.get().is_negative()
911 }
912 }
913914/// Compute the `rem_euclid` of this type with its unsigned type equivalent
915// Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
916 // Also because this isn't implemented for normal types in std.
917#[must_use = "this returns the result of the operation, without modifying the original"]
918 #[track_caller]
919 #[inline]
920 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
921const fn rem_euclid_unsigned(
922 rhs: $internal,
923 range_len: $unsigned_type
924) -> $unsigned_type {
925#[allow(unused_comparisons)]
926if rhs >= 0 {
927 (rhs as $unsigned_type) % range_len
928 } else {
929// Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
930 // Can't write -ux or ux::abs() method. This gets around compilation error.
931 // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
932let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
933// Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
934 // Also = 0 in mod range_len arithmetic.
935 // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
936 // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
937 // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
938 // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
939((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
940 }
941 }
942943/// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
944 /// bounds.
945#[must_use = "this returns the result of the operation, without modifying the original"]
946 #[inline]
947 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
948pub const fn wrapping_add(self, rhs: $internal) -> Self {
949const { assert!(MIN <= MAX); }
950// Forward to internal type's impl if same as type.
951if MIN == $internal::MIN && MAX == $internal::MAX {
952// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
953return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
954 }
955956let inner = self.get();
957958// Won't overflow because of std impl forwarding.
959let range_len = MAX.abs_diff(MIN) + 1;
960961// Calculate the offset with proper handling for negative rhs
962let offset = Self::rem_euclid_unsigned(rhs, range_len);
963964let greater_vals = MAX.abs_diff(inner);
965// No wrap
966if offset <= greater_vals {
967// Safety:
968 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
969 // if inner < 0: Same as >=0 with caveat:
970 // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
971 // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
972 // (the difference doesn't matter since it won't overflow),
973 // but unsigned integers don't have either method so it won't compile that way.
974unsafe { Self::new_unchecked(
975 ((inner as $unsigned_type).wrapping_add(offset)) as $internal
976) }
977 }
978// Wrap
979else {
980// Safety:
981 // - offset < range_len by rem_euclid (MIN + ... safe)
982 // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
983 //
984 // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
985unsafe { Self::new_unchecked(
986 ((MIN as $unsigned_type).wrapping_add(
987 offset - (greater_vals + 1)
988 )) as $internal
989) }
990 }
991 }
992993/// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
994 /// bounds.
995#[must_use = "this returns the result of the operation, without modifying the original"]
996 #[inline]
997 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
998pub const fn wrapping_sub(self, rhs: $internal) -> Self {
999const { assert!(MIN <= MAX); }
1000// Forward to internal type's impl if same as type.
1001if MIN == $internal::MIN && MAX == $internal::MAX {
1002// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1003return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
1004 }
10051006let inner = self.get();
10071008// Won't overflow because of std impl forwarding.
1009let range_len = MAX.abs_diff(MIN) + 1;
10101011// Calculate the offset with proper handling for negative rhs
1012let offset = Self::rem_euclid_unsigned(rhs, range_len);
10131014let lesser_vals = MIN.abs_diff(inner);
1015// No wrap
1016if offset <= lesser_vals {
1017// Safety:
1018 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1019 // if inner < 0: Same as >=0 with caveat:
1020 // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
1021 // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
1022 // (the difference doesn't matter since it won't overflow below 0),
1023 // but unsigned integers don't have either method so it won't compile that way.
1024unsafe { Self::new_unchecked(
1025 ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
1026) }
1027 }
1028// Wrap
1029else {
1030// Safety:
1031 // - offset < range_len by rem_euclid (MAX - ... safe)
1032 // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
1033 //
1034 // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
1035unsafe { Self::new_unchecked(
1036 ((MAX as $unsigned_type).wrapping_sub(
1037 offset - (lesser_vals + 1)
1038 )) as $internal
1039) }
1040 }
1041 }
1042 }
10431044impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
1045/// The value used as the niche. Must not be in the range `MIN..=MAX`.
1046const NICHE: $internal = match (MIN, MAX) {
1047 ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
1048 ($internal::MIN, _) => $internal::MAX,
1049 (_, _) => $internal::MIN,
1050 };
10511052/// An optional ranged value that is not present.
1053#[allow(non_upper_case_globals)]
1054pub const None: Self = Self(Self::NICHE);
10551056/// Creates an optional ranged value that is present.
1057#[allow(non_snake_case)]
1058 #[inline(always)]
1059pub const fn Some(value: $type<MIN, MAX>) -> Self {
1060const { assert!(MIN <= MAX); }
1061Self(value.get())
1062 }
10631064/// Returns the value as the standard library's [`Option`] type.
1065#[inline(always)]
1066pub const fn get(self) -> Option<$type<MIN, MAX>> {
1067const { assert!(MIN <= MAX); }
1068if self.0 == Self::NICHE {
1069None
1070} else {
1071// Safety: A stored value that is not the niche is always in range.
1072Some(unsafe { $type::new_unchecked(self.0) })
1073 }
1074 }
10751076/// Creates an optional ranged integer without checking the value.
1077 ///
1078 /// # Safety
1079 ///
1080 /// The value must be within the range `MIN..=MAX`. As the value used for niche
1081 /// value optimization is unspecified, the provided value must not be the niche
1082 /// value.
1083#[inline(always)]
1084 #[track_caller]
1085pub const unsafe fn some_unchecked(value: $internal) -> Self {
1086const { assert!(MIN <= MAX); }
1087// Safety: The caller must ensure that the value is in range.
1088unsafe { assert_unchecked(MIN <= value && value <= MAX) };
1089Self(value)
1090 }
10911092/// Obtain the inner value of the struct. This is useful for comparisons.
1093#[inline(always)]
1094pub(crate) const fn inner(self) -> $internal {
1095const { assert!(MIN <= MAX); }
1096self.0
1097}
10981099/// Obtain the value of the struct as an `Option` of the primitive type.
1100 ///
1101 /// A call to this function will output a hint to the compiler that the value is in
1102 /// range. In general this will help the optimizer to generate better code, but in edge
1103 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
1104#[doc = concat!(
1105"use [`", stringify!($optional_type), "::get_primitive_without_hint`]."
1106)]
1107 #[inline(always)]
1108pub const fn get_primitive(self) -> Option<$internal> {
1109const { assert!(MIN <= MAX); }
1110Some(const_try_opt!(self.get()).get())
1111 }
11121113/// Obtain the value of the struct as an `Option` of the primitive type.
1114 ///
1115#[doc = concat!(
1116"The returned value is identical to [`", stringify!($optional_type), "::",
1117"get_primitive`]."
1118)]
1119/// Unlike `get_primitive`, no hints are output to the compiler indicating the range
1120 /// that the value is in. Depending on the scenario, this may with be helpful or harmful
1121 /// too optimization.
1122#[inline(always)]
1123pub const fn get_primitive_without_hint(self) -> Option<$internal> {
1124const { assert!(MIN <= MAX); }
1125Some(const_try_opt!(self.get()).get_without_hint())
1126 }
11271128/// Returns `true` if the value is the niche value.
1129#[inline(always)]
1130pub const fn is_none(&self) -> bool {
1131const { assert!(MIN <= MAX); }
1132self.get().is_none()
1133 }
11341135/// Returns `true` if the value is not the niche value.
1136#[inline(always)]
1137pub const fn is_some(&self) -> bool {
1138const { assert!(MIN <= MAX); }
1139self.get().is_some()
1140 }
1141 }
11421143impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
1144#[inline(always)]
1145fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1146const { assert!(MIN <= MAX); }
1147self.get().fmt(f)
1148 }
1149 }
11501151impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
1152#[inline(always)]
1153fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1154const { assert!(MIN <= MAX); }
1155self.get().fmt(f)
1156 }
1157 }
11581159impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
1160#[inline(always)]
1161fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1162const { assert!(MIN <= MAX); }
1163self.get().fmt(f)
1164 }
1165 }
11661167#[cfg(feature = "powerfmt")]
1168impl<
1169const MIN: $internal,
1170const MAX: $internal,
1171 > smart_display::SmartDisplay for $type<MIN, MAX> {
1172type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
11731174#[inline(always)]
1175fn metadata(
1176&self,
1177 f: smart_display::FormatterOptions,
1178 ) -> smart_display::Metadata<'_, Self> {
1179const { assert!(MIN <= MAX); }
1180self.get_ref().metadata(f).reuse()
1181 }
11821183#[inline(always)]
1184fn fmt_with_metadata(
1185&self,
1186 f: &mut fmt::Formatter<'_>,
1187 metadata: smart_display::Metadata<'_, Self>,
1188 ) -> fmt::Result {
1189const { assert!(MIN <= MAX); }
1190self.get().fmt_with_metadata(f, metadata.reuse())
1191 }
1192 }
11931194impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
1195#[inline(always)]
1196fn default() -> Self {
1197const { assert!(MIN <= MAX); }
1198Self::None
1199 }
1200 }
12011202impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
1203#[inline(always)]
1204fn as_ref(&self) -> &$internal {
1205const { assert!(MIN <= MAX); }
1206&self.get_ref()
1207 }
1208 }
12091210impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
1211#[inline(always)]
1212fn borrow(&self) -> &$internal {
1213const { assert!(MIN <= MAX); }
1214&self.get_ref()
1215 }
1216 }
12171218impl<
1219const MIN_A: $internal,
1220const MAX_A: $internal,
1221const MIN_B: $internal,
1222const MAX_B: $internal,
1223 > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1224#[inline(always)]
1225fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
1226const {
1227assert!(MIN_A <= MAX_A);
1228assert!(MIN_B <= MAX_B);
1229 }
1230self.get() == other.get()
1231 }
1232 }
12331234impl<
1235const MIN_A: $internal,
1236const MAX_A: $internal,
1237const MIN_B: $internal,
1238const MAX_B: $internal,
1239 > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1240#[inline(always)]
1241fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
1242const {
1243assert!(MIN_A <= MAX_A);
1244assert!(MIN_B <= MAX_B);
1245 }
1246self.inner() == other.inner()
1247 }
1248 }
12491250impl<
1251const MIN_A: $internal,
1252const MAX_A: $internal,
1253const MIN_B: $internal,
1254const MAX_B: $internal,
1255 > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1256#[inline(always)]
1257fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
1258const {
1259assert!(MIN_A <= MAX_A);
1260assert!(MIN_B <= MAX_B);
1261 }
1262self.get().partial_cmp(&other.get())
1263 }
1264 }
12651266impl<
1267const MIN_A: $internal,
1268const MAX_A: $internal,
1269const MIN_B: $internal,
1270const MAX_B: $internal,
1271 > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1272#[inline]
1273fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
1274const {
1275assert!(MIN_A <= MAX_A);
1276assert!(MIN_B <= MAX_B);
1277 }
1278if self.is_none() && other.is_none() {
1279Some(Ordering::Equal)
1280 } else if self.is_none() {
1281Some(Ordering::Less)
1282 } else if other.is_none() {
1283Some(Ordering::Greater)
1284 } else {
1285self.inner().partial_cmp(&other.inner())
1286 }
1287 }
1288 }
12891290impl<
1291const MIN: $internal,
1292const MAX: $internal,
1293 > Ord for $optional_type<MIN, MAX> {
1294#[inline]
1295fn cmp(&self, other: &Self) -> Ordering {
1296const { assert!(MIN <= MAX); }
1297if self.is_none() && other.is_none() {
1298 Ordering::Equal
1299 } else if self.is_none() {
1300 Ordering::Less
1301 } else if other.is_none() {
1302 Ordering::Greater
1303 } else {
1304self.inner().cmp(&other.inner())
1305 }
1306 }
1307 }
13081309impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
1310#[inline(always)]
1311fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1312const { assert!(MIN <= MAX); }
1313self.get().fmt(f)
1314 }
1315 }
13161317impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
1318#[inline(always)]
1319fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1320const { assert!(MIN <= MAX); }
1321self.get().fmt(f)
1322 }
1323 }
13241325impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
1326#[inline(always)]
1327fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1328const { assert!(MIN <= MAX); }
1329self.get().fmt(f)
1330 }
1331 }
13321333impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
1334#[inline(always)]
1335fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1336const { assert!(MIN <= MAX); }
1337self.get().fmt(f)
1338 }
1339 }
13401341impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
1342#[inline(always)]
1343fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1344const { assert!(MIN <= MAX); }
1345self.get().fmt(f)
1346 }
1347 }
13481349impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
1350#[inline(always)]
1351fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1352const { assert!(MIN <= MAX); }
1353self.get().fmt(f)
1354 }
1355 }
13561357if_unsigned! { $is_signed
1358impl From<NonZero<$internal>> for $type<1, { $internal::MAX }> {
1359#[inline(always)]
1360fn from(value: NonZero<$internal>) -> Self {
1361Self::from_nonzero(value)
1362 }
1363 }
13641365impl From<$type<1, { $internal::MAX }>> for NonZero<$internal> {
1366#[inline(always)]
1367fn from(value: $type<1, { $internal::MAX }>) -> Self {
1368 value.to_nonzero()
1369 }
1370 }
1371 }
13721373impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
1374#[inline(always)]
1375fn from(value: $type<MIN, MAX>) -> Self {
1376const { assert!(MIN <= MAX); }
1377 value.get()
1378 }
1379 }
13801381impl<
1382const MIN: $internal,
1383const MAX: $internal,
1384 > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
1385#[inline(always)]
1386fn from(value: $type<MIN, MAX>) -> Self {
1387const { assert!(MIN <= MAX); }
1388Self::Some(value)
1389 }
1390 }
13911392impl<
1393const MIN: $internal,
1394const MAX: $internal,
1395 > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
1396#[inline(always)]
1397fn from(value: Option<$type<MIN, MAX>>) -> Self {
1398const { assert!(MIN <= MAX); }
1399match value {
1400Some(value) => Self::Some(value),
1401None => Self::None,
1402 }
1403 }
1404 }
14051406impl<
1407const MIN: $internal,
1408const MAX: $internal,
1409 > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
1410#[inline(always)]
1411fn from(value: $optional_type<MIN, MAX>) -> Self {
1412const { assert!(MIN <= MAX); }
1413 value.get()
1414 }
1415 }
14161417impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
1418type Error = TryFromIntError;
14191420#[inline]
1421fn try_from(value: $internal) -> Result<Self, Self::Error> {
1422const { assert!(MIN <= MAX); }
1423Self::new(value).ok_or(TryFromIntError)
1424 }
1425 }
14261427impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
1428type Err = ParseIntError;
14291430#[inline]
1431fn from_str(s: &str) -> Result<Self, Self::Err> {
1432const { assert!(MIN <= MAX); }
1433let value = s.parse::<$internal>().map_err(|e| ParseIntError {
1434 kind: e.kind().clone()
1435 })?;
1436if value < MIN {
1437Err(ParseIntError { kind: IntErrorKind::NegOverflow })
1438 } else if value > MAX {
1439Err(ParseIntError { kind: IntErrorKind::PosOverflow })
1440 } else {
1441// Safety: The value was previously checked for validity.
1442Ok(unsafe { Self::new_unchecked(value) })
1443 }
1444 }
1445 }
14461447 $(impl<
1448const MIN_SRC: $from_internal,
1449const MAX_SRC: $from_internal,
1450const MIN_DST: $internal,
1451const MAX_DST: $internal,
1452 > From<$from<MIN_SRC, MAX_SRC>> for $type<MIN_DST, MAX_DST>
1453 {
1454#[inline(always)]
1455 #[allow(trivial_numeric_casts, unused_comparisons)]
1456fn from(value: $from<MIN_SRC, MAX_SRC>) -> Self {
1457const {
1458assert!(MIN_SRC <= MAX_SRC, "source range is invalid");
1459assert!(MIN_DST <= MAX_DST, "target range is invalid");
14601461match ($from_internal::MIN == 0, $internal::MIN == 0) {
1462// unsigned -> unsigned
1463(true, true) => {
1464assert!(
1465 MIN_SRC as u128 >= MIN_DST as u128,
1466"minimum value cannot be represented in the target range"
1467);
1468assert!(
1469 MAX_SRC as u128 <= MAX_DST as u128,
1470"maximum value cannot be represented in the target range"
1471);
1472 }
1473// signed -> signed
1474(false, false) => {
1475assert!(
1476 MIN_SRC as i128 >= MIN_DST as i128,
1477"minimum value cannot be represented in the target range"
1478);
1479assert!(
1480 MAX_SRC as i128 <= MAX_DST as i128,
1481"maximum value cannot be represented in the target range"
1482);
1483 }
1484// unsigned -> signed
1485(true, false) => {
1486assert!(
1487 MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128,
1488"minimum value cannot be represented in the target range"
1489);
1490assert!(
1491 MAX_DST >= 0
1492&& MAX_SRC as u128 <= i128::MAX as u128
1493 && MAX_SRC as i128 <= MAX_DST as i128,
1494"maximum value cannot be represented in the target range"
1495);
1496 }
1497// signed -> unsigned
1498(false, true) => {
1499assert!(
1500 MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128,
1501"minimum value cannot be represented in the target range"
1502);
1503assert!(
1504 MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128,
1505"maximum value cannot be represented in the target range"
1506);
1507 }
1508 }
1509 }
15101511// Safety: The source range is a subset of the destination range.
1512unsafe { $type::new_unchecked(value.get() as $internal) }
1513 }
1514 })+
15151516#[cfg(feature = "serde")]
1517impl<const MIN: $internal, const MAX: $internal> serde_core::Serialize for $type<MIN, MAX> {
1518#[inline(always)]
1519fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1520 {
1521const { assert!(MIN <= MAX); }
1522self.get().serialize(serializer)
1523 }
1524 }
15251526#[cfg(feature = "serde")]
1527impl<
1528const MIN: $internal,
1529const MAX: $internal,
1530 > serde_core::Serialize for $optional_type<MIN, MAX> {
1531#[inline(always)]
1532fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1533 {
1534const { assert!(MIN <= MAX); }
1535self.get().serialize(serializer)
1536 }
1537 }
15381539#[cfg(feature = "serde")]
1540impl<
1541'de,
1542const MIN: $internal,
1543const MAX: $internal,
1544 > serde_core::Deserialize<'de> for $type<MIN, MAX> {
1545#[inline]
1546fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1547 -> Result<Self, D::Error>
1548 {
1549const { assert!(MIN <= MAX); }
1550let internal = <$internal>::deserialize(deserializer)?;
1551Self::new(internal).ok_or_else(||
1552 <D::Error as serde_core::de::Error>::invalid_value(
1553 serde_core::de::Unexpected::Other("integer"),
1554#[cfg(feature = "alloc")] {
1555&alloc::format!("an integer in the range {}..={}", MIN, MAX).as_ref()
1556 },
1557#[cfg(not(feature = "alloc"))] {
1558&"an integer in the valid range"
1559}
1560 )
1561 )
1562 }
1563 }
15641565#[cfg(feature = "serde")]
1566impl<
1567'de,
1568const MIN: $internal,
1569const MAX: $internal,
1570 > serde_core::Deserialize<'de> for $optional_type<MIN, MAX> {
1571#[inline]
1572fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1573 -> Result<Self, D::Error>
1574 {
1575const { assert!(MIN <= MAX); }
1576Ok(Self::Some($type::<MIN, MAX>::deserialize(deserializer)?))
1577 }
1578 }
15791580#[cfg(feature = "rand08")]
1581impl<
1582const MIN: $internal,
1583const MAX: $internal,
1584 > rand08::distributions::Distribution<$type<MIN, MAX>> for rand08::distributions::Standard {
1585#[inline]
1586fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1587const { assert!(MIN <= MAX); }
1588$type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1589 }
1590 }
15911592if_not_manual_rand_09! {
1593 [$($($skips)+)?]
1594#[cfg(feature = "rand09")]
1595impl<
1596const MIN: $internal,
1597const MAX: $internal,
1598 > rand09::distr::Distribution<$type<MIN, MAX>> for rand09::distr::StandardUniform {
1599#[inline]
1600fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1601const { assert!(MIN <= MAX); }
1602$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1603 }
1604 }
1605 }
16061607#[cfg(feature = "rand08")]
1608impl<
1609const MIN: $internal,
1610const MAX: $internal,
1611 > rand08::distributions::Distribution<$optional_type<MIN, MAX>>
1612for rand08::distributions::Standard {
1613#[inline]
1614fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1615const { assert!(MIN <= MAX); }
1616 rng.r#gen::<Option<$type<MIN, MAX>>>().into()
1617 }
1618 }
16191620#[cfg(feature = "rand09")]
1621impl<
1622const MIN: $internal,
1623const MAX: $internal,
1624 > rand09::distr::Distribution<$optional_type<MIN, MAX>>
1625for rand09::distr::StandardUniform {
1626#[inline]
1627fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1628const { assert!(MIN <= MAX); }
1629if rng.random() {
1630$optional_type::None
1631} else {
1632$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1633 }
1634 }
1635 }
16361637#[cfg(feature = "num")]
1638impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
1639#[inline(always)]
1640fn min_value() -> Self {
1641const { assert!(MIN <= MAX); }
1642Self::MIN
1643 }
16441645#[inline(always)]
1646fn max_value() -> Self {
1647const { assert!(MIN <= MAX); }
1648Self::MAX
1649 }
1650 }
16511652#[cfg(feature = "quickcheck")]
1653impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
1654#[inline]
1655fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1656const { assert!(MIN <= MAX); }
1657// Safety: The `rem_euclid` call and addition ensure that the value is in range.
1658unsafe {
1659Self::new_unchecked($internal::arbitrary(g).rem_euclid(MAX - MIN + 1) + MIN)
1660 }
1661 }
16621663#[inline]
1664fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1665 ::alloc::boxed::Box::new(
1666self.get()
1667 .shrink()
1668 .filter_map(Self::new)
1669 )
1670 }
1671 }
16721673#[cfg(feature = "quickcheck")]
1674impl<
1675const MIN: $internal,
1676const MAX: $internal,
1677 > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
1678#[inline]
1679fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1680const { assert!(MIN <= MAX); }
1681Option::<$type<MIN, MAX>>::arbitrary(g).into()
1682 }
16831684#[inline]
1685fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1686 ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
1687 }
1688 }
1689 )*};
1690}
16911692#[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]
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! {
1693RangedU8 {
1694 mod_name: ranged_u8
1695 internal: u8
1696 signed: false
1697unsigned: u8
1698 optional: OptionRangedU81699 from: [
1700RangedU16(u16)
1701RangedU32(u32)
1702RangedU64(u64)
1703RangedU128(u128)
1704RangedUsize(usize)
1705RangedI8(i8)
1706RangedI16(i16)
1707RangedI32(i32)
1708RangedI64(i64)
1709RangedI128(i128)
1710RangedIsize(isize)
1711 ]
1712 }
1713RangedU16 {
1714 mod_name: ranged_u16
1715 internal: u16
1716 signed: false
1717unsigned: u16
1718 optional: OptionRangedU161719 from: [
1720RangedU8(u8)
1721RangedU32(u32)
1722RangedU64(u64)
1723RangedU128(u128)
1724RangedUsize(usize)
1725RangedI8(i8)
1726RangedI16(i16)
1727RangedI32(i32)
1728RangedI64(i64)
1729RangedI128(i128)
1730RangedIsize(isize)
1731 ]
1732 }
1733RangedU32 {
1734 mod_name: ranged_u32
1735 internal: u32
1736 signed: false
1737unsigned: u32
1738 optional: OptionRangedU321739 from: [
1740RangedU8(u8)
1741RangedU16(u16)
1742RangedU64(u64)
1743RangedU128(u128)
1744RangedUsize(usize)
1745RangedI8(i8)
1746RangedI16(i16)
1747RangedI32(i32)
1748RangedI64(i64)
1749RangedI128(i128)
1750RangedIsize(isize)
1751 ]
1752 }
1753RangedU64 {
1754 mod_name: ranged_u64
1755 internal: u64
1756 signed: false
1757unsigned: u64
1758 optional: OptionRangedU641759 from: [
1760RangedU8(u8)
1761RangedU16(u16)
1762RangedU32(u32)
1763RangedU128(u128)
1764RangedUsize(usize)
1765RangedI8(i8)
1766RangedI16(i16)
1767RangedI32(i32)
1768RangedI64(i64)
1769RangedI128(i128)
1770RangedIsize(isize)
1771 ]
1772 }
1773RangedU128 {
1774 mod_name: ranged_u128
1775 internal: u128
1776 signed: false
1777unsigned: u128
1778 optional: OptionRangedU1281779 from: [
1780RangedU8(u8)
1781RangedU16(u16)
1782RangedU32(u32)
1783RangedU64(u64)
1784RangedUsize(usize)
1785RangedI8(i8)
1786RangedI16(i16)
1787RangedI32(i32)
1788RangedI64(i64)
1789RangedI128(i128)
1790RangedIsize(isize)
1791 ]
1792 }
1793RangedUsize {
1794 mod_name: ranged_usize
1795 internal: usize
1796 signed: false
1797unsigned: usize
1798 optional: OptionRangedUsize1799 from: [
1800RangedU8(u8)
1801RangedU16(u16)
1802RangedU32(u32)
1803RangedU64(u64)
1804RangedU128(u128)
1805RangedI8(i8)
1806RangedI16(i16)
1807RangedI32(i32)
1808RangedI64(i64)
1809RangedI128(i128)
1810RangedIsize(isize)
1811 ]
1812 manual: [rand_09]
1813 }
1814RangedI8 {
1815 mod_name: ranged_i8
1816 internal: i8
1817 signed: true
1818unsigned: u8
1819 optional: OptionRangedI81820 from: [
1821RangedU8(u8)
1822RangedU16(u16)
1823RangedU32(u32)
1824RangedU64(u64)
1825RangedU128(u128)
1826RangedUsize(usize)
1827RangedI16(i16)
1828RangedI32(i32)
1829RangedI64(i64)
1830RangedI128(i128)
1831RangedIsize(isize)
1832 ]
1833 }
1834RangedI16 {
1835 mod_name: ranged_i16
1836 internal: i16
1837 signed: true
1838unsigned: u16
1839 optional: OptionRangedI161840 from: [
1841RangedU8(u8)
1842RangedU16(u16)
1843RangedU32(u32)
1844RangedU64(u64)
1845RangedU128(u128)
1846RangedUsize(usize)
1847RangedI8(i8)
1848RangedI32(i32)
1849RangedI64(i64)
1850RangedI128(i128)
1851RangedIsize(isize)
1852 ]
1853 }
1854RangedI32 {
1855 mod_name: ranged_i32
1856 internal: i32
1857 signed: true
1858unsigned: u32
1859 optional: OptionRangedI321860 from: [
1861RangedU8(u8)
1862RangedU16(u16)
1863RangedU32(u32)
1864RangedU64(u64)
1865RangedU128(u128)
1866RangedUsize(usize)
1867RangedI8(i8)
1868RangedI16(i16)
1869RangedI64(i64)
1870RangedI128(i128)
1871RangedIsize(isize)
1872 ]
1873 }
1874RangedI64 {
1875 mod_name: ranged_i64
1876 internal: i64
1877 signed: true
1878unsigned: u64
1879 optional: OptionRangedI641880 from: [
1881RangedU8(u8)
1882RangedU16(u16)
1883RangedU32(u32)
1884RangedU64(u64)
1885RangedU128(u128)
1886RangedUsize(usize)
1887RangedI8(i8)
1888RangedI16(i16)
1889RangedI32(i32)
1890RangedI128(i128)
1891RangedIsize(isize)
1892 ]
1893 }
1894RangedI128 {
1895 mod_name: ranged_i128
1896 internal: i128
1897 signed: true
1898unsigned: u128
1899 optional: OptionRangedI1281900 from: [
1901RangedU8(u8)
1902RangedU16(u16)
1903RangedU32(u32)
1904RangedU64(u64)
1905RangedU128(u128)
1906RangedUsize(usize)
1907RangedI8(i8)
1908RangedI16(i16)
1909RangedI32(i32)
1910RangedI64(i64)
1911RangedIsize(isize)
1912 ]
1913 }
1914RangedIsize {
1915 mod_name: ranged_isize
1916 internal: isize
1917 signed: true
1918unsigned: usize
1919 optional: OptionRangedIsize1920 from: [
1921RangedU8(u8)
1922RangedU16(u16)
1923RangedU32(u32)
1924RangedU64(u64)
1925RangedU128(u128)
1926RangedUsize(usize)
1927RangedI8(i8)
1928RangedI16(i16)
1929RangedI32(i32)
1930RangedI64(i64)
1931RangedI128(i128)
1932 ]
1933 manual: [rand_09]
1934 }
1935}19361937#[cfg(feature = "rand09")]
1938impl<const MIN: usize, const MAX: usize> rand09::distr::Distribution<RangedUsize<MIN, MAX>>
1939for rand09::distr::StandardUniform
1940{
1941#[inline]
1942fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
1943const {
1944assert!(MIN <= MAX);
1945 }
19461947#[cfg(target_pointer_width = "16")]
1948let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
1949#[cfg(target_pointer_width = "32")]
1950let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
1951#[cfg(target_pointer_width = "64")]
1952let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
1953#[cfg(not(any(
1954 target_pointer_width = "16",
1955 target_pointer_width = "32",
1956 target_pointer_width = "64"
1957)))]
1958compile_error("platform has unusual (and unsupported) pointer width");
19591960 RangedUsize::new(value).expect("rand failed to generate a valid value")
1961 }
1962}
19631964#[cfg(feature = "rand09")]
1965impl<const MIN: isize, const MAX: isize> rand09::distr::Distribution<RangedIsize<MIN, MAX>>
1966for rand09::distr::StandardUniform
1967{
1968#[inline]
1969fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
1970const {
1971assert!(MIN <= MAX);
1972 }
19731974#[cfg(target_pointer_width = "16")]
1975let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
1976#[cfg(target_pointer_width = "32")]
1977let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
1978#[cfg(target_pointer_width = "64")]
1979let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
1980#[cfg(not(any(
1981 target_pointer_width = "16",
1982 target_pointer_width = "32",
1983 target_pointer_width = "64"
1984)))]
1985compile_error("platform has unusual (and unsupported) pointer width");
19861987 RangedIsize::new(value).expect("rand failed to generate a valid value")
1988 }
1989}