1//! `deranged` is a proof-of-concept implementation of ranged integers.
23#![cfg_attr(docsrs, feature(doc_cfg))]
4#![no_std]
5#![doc(test(attr(deny(warnings))))]
67#[cfg(all(feature = "alloc", any(feature = "serde", feature = "quickcheck")))]
8extern crate alloc;
910#[cfg(test)]
11mod tests;
12mod unsafe_wrapper;
1314use core::borrow::Borrow;
15use core::cmp::Ordering;
16use core::error::Error;
17use core::fmt;
18use core::hint::assert_unchecked;
19use core::num::{IntErrorKind, NonZero};
20use core::str::FromStr;
2122/// A macro to define a ranged integer with an automatically computed inner type.
23///
24/// The minimum and maximum values are provided as integer literals, and the macro will compute an
25/// appropriate inner type to represent the range. This will be the smallest integer type that can
26/// store both the minimum and maximum values, with a preference for unsigned types if both are
27/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
28/// to either or both of the minimum and maximum values, respectively.
29///
30/// # Examples
31///
32/// ```rust,ignore
33/// int!(0, 100); // RangedU8<0, 100>
34/// int!(0i, 100); // RangedI8<0, 100>
35/// int!(-5, 5); // RangedI8<-5, 5>
36/// int!(-5u, 5); // compile error (-5 cannot be unsigned)
37/// ```
38#[cfg(docsrs)]
39#[doc(cfg(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(docsrs)]
62#[doc(cfg(feature = "macros"))]
63#[macro_export]
64macro_rules! opt_int {
65 ($min:literal, $max:literal) => {};
66}
6768#[cfg(all(not(docsrs), feature = "macros"))]
69pub use deranged_macros::int;
70#[cfg(all(not(docsrs), feature = "macros"))]
71pub use deranged_macros::opt_int;
72#[cfg(feature = "powerfmt")]
73use powerfmt::smart_display;
7475use crate::unsafe_wrapper::Unsafe;
7677/// The error type returned when a checked integral type conversion fails.
78#[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)]
79pub struct TryFromIntError;
8081impl fmt::Displayfor TryFromIntError {
82#[inline]
83fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84f.write_str("out of range integral type conversion attempted")
85 }
86}
87impl Errorfor TryFromIntError {}
8889/// An error which can be returned when parsing an integer.
90///
91/// This error is used as the error type for the `from_str_radix()` functions on ranged integer
92/// types, such as [`RangedI8::from_str_radix`].
93///
94/// # Potential causes
95///
96/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
97/// in the string e.g., when it is obtained from the standard input.
98/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
99///
100/// # Example
101///
102/// ```rust
103/// # use deranged::RangedI32;
104/// if let Err(e) = RangedI32::<0, 10>::from_str_radix("a12", 10) {
105/// println!("Failed conversion to RangedI32: {e}");
106/// }
107/// ```
108#[allow(missing_copy_implementations)] // same as `std`
109#[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)]
110pub struct ParseIntError {
111#[allow(clippy::missing_docs_in_private_items)]
112kind: IntErrorKind,
113}
114115impl ParseIntError {
116/// Outputs the detailed cause of parsing an integer failing.
117// This function is not const because the counterpart of stdlib isn't
118#[allow(clippy::missing_const_for_fn)]
119 #[inline(always)]
120pub fn kind(&self) -> &IntErrorKind {
121&self.kind
122 }
123}
124125impl fmt::Displayfor ParseIntError {
126#[inline]
127fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128match self.kind {
129 IntErrorKind::Empty => "cannot parse integer from empty string",
130 IntErrorKind::InvalidDigit => "invalid digit found in string",
131 IntErrorKind::PosOverflow => "number too large to fit in target type",
132 IntErrorKind::NegOverflow => "number too small to fit in target type",
133 IntErrorKind::Zero => "number would be zero for non-zero type",
134_ => "Unknown Int error kind",
135 }
136 .fmt(f)
137 }
138}
139140impl Errorfor ParseIntError {}
141142/// `?` for `Option` types, usable in `const` contexts.
143macro_rules! const_try_opt {
144 ($e:expr) => {
145match $e {
146Some(value) => value,
147None => return None,
148 }
149 };
150}
151152/// Output the given tokens if the type is signed, otherwise output nothing.
153macro_rules! if_signed {
154 (true $($x:tt)*) => { $($x)*};
155 (false $($x:tt)*) => {};
156}
157158/// Output the given tokens if the type is unsigned, otherwise output nothing.
159macro_rules! if_unsigned {
160 (true $($x:tt)*) => {};
161 (false $($x:tt)*) => { $($x)* };
162}
163164/// `"A"` if `true`, `"An"` if `false`.
165macro_rules! article {
166 (true) => {
167"An"
168};
169 (false) => {
170"A"
171};
172}
173174/// Output the provided code if and only if the list does not include `rand_09`.
175#[allow(unused_macro_rules)]
176macro_rules! if_not_manual_rand_09 {
177 ([rand_09 $($rest:ident)*] $($output:tt)*) => {};
178 ([] $($output:tt)*) => {
179 $($output)*
180 };
181 ([$first:ident $($rest:ident)*] $($output:tt)*) => {
182if_not_manual_rand_09!([$($rest)*] $($output)*);
183 };
184}
185186/// Output the provided code if and only if the list does not include `rand_010`.
187#[allow(unused_macro_rules)]
188macro_rules! if_not_manual_rand_010 {
189 ([rand_010 $($rest:ident)*] $($output:tt)*) => {};
190 ([] $($output:tt)*) => {
191 $($output)*
192 };
193 ([$first:ident $($rest:ident)*] $($output:tt)*) => {
194if_not_manual_rand_010!([$($rest)*] $($output)*);
195 };
196}
197198/// Implement a ranged integer type.
199macro_rules! impl_ranged {
200 ($(
201$type:ident {
202 mod_name: $mod_name:ident
203 alias: $alias:ident
204 internal: $internal:ident
205 signed: $is_signed:ident
206 unsigned: $unsigned_type:ident
207 optional: $optional_type:ident
208 optional_alias: $optional_alias:ident
209 from: [$($from:ident($from_internal:ident))+]
210 $(manual: [$($skips:ident)+])?
211}
212 )*) => {$(
213#[doc = concat!("Equivalent to `", stringify!($type), "`")]
214 #[expect(non_camel_case_types, reason = "symmetry with primitives")]
215pub type $alias<const MIN: $internal, const MAX: $internal> = $type<MIN, MAX>;
216217#[doc = concat!("Equivalent to `", stringify!($optional_type), "`")]
218 #[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
219pub type $optional_alias<const MIN: $internal, const MAX: $internal>
220 = $optional_type<MIN, MAX>;
221222#[doc = concat!(
223article!($is_signed),
224" `",
225stringify!($internal),
226"` that is known to be in the range `MIN..=MAX`.",
227 )]
228 #[repr(transparent)]
229 #[derive(Clone, Copy, Eq, Ord, Hash)]
230pub struct $type<const MIN: $internal, const MAX: $internal>(
231Unsafe<$internal>,
232 );
233234#[doc = concat!(
235"An optional `",
236stringify!($type),
237"`; similar to `Option<",
238stringify!($type),
239">` with better optimization.",
240 )]
241///
242#[doc = concat!(
243"If `MIN` is [`",
244stringify!($internal),
245"::MIN`] _and_ `MAX` is [`",
246stringify!($internal)
247 ,"::MAX`] then compilation will fail. This is because there is no way to represent \
248 the niche value.",
249 )]
250///
251 /// This type is useful when you need to store an optional ranged value in a struct, but
252 /// do not want the overhead of an `Option` type. This reduces the size of the struct
253 /// overall, and is particularly useful when you have a large number of optional fields.
254 /// Note that most operations must still be performed on the [`Option`] type, which is
255#[doc = concat!("obtained with [`", stringify!($optional_type), "::get`].")]
256 #[repr(transparent)]
257 #[derive(Clone, Copy, Eq, Hash)]
258pub struct $optional_type<const MIN: $internal, const MAX: $internal>(
259$internal,
260 );
261262impl $type<0, 0> {
263#[doc = concat!("A ", stringify!($type), " that is always `VALUE`.")]
264 #[inline(always)]
265pub const fn exact<const VALUE: $internal>() -> $type<VALUE, VALUE> {
266// Safety: The value is the only one in range.
267unsafe { $type::new_unchecked(VALUE) }
268 }
269 }
270271if_unsigned! { $is_signed
272impl $type<1, { $internal::MAX }> {
273/// Creates a ranged integer from a non-zero value.
274#[inline(always)]
275pub const fn from_nonzero(value: NonZero<$internal>) -> Self {
276// Safety: The value is non-zero, so it is in range.
277unsafe { Self::new_unchecked(value.get()) }
278 }
279280/// Creates a non-zero value from a ranged integer.
281#[inline(always)]
282pub const fn to_nonzero(self) -> NonZero<$internal> {
283// Safety: The value is in range, so it is non-zero.
284unsafe { NonZero::new_unchecked(self.get()) }
285 }
286 }}
287288impl<const MIN: $internal, const MAX: $internal> $type<MIN, MAX> {
289/// The smallest value that can be represented by this type.
290// Safety: `MIN` is in range by definition.
291pub const MIN: Self = Self::new_static::<MIN>();
292293/// The largest value that can be represented by this type.
294// Safety: `MAX` is in range by definition.
295pub const MAX: Self = Self::new_static::<MAX>();
296297/// Creates a ranged integer without checking the value.
298 ///
299 /// # Safety
300 ///
301 /// The value must be within the range `MIN..=MAX`.
302#[track_caller]
303 #[inline(always)]
304pub const unsafe fn new_unchecked(value: $internal) -> Self {
305const { assert!(MIN <= MAX); }
306// Safety: The caller must ensure that the value is in range.
307unsafe {
308 assert_unchecked(MIN <= value && value <= MAX);
309Self(Unsafe::new(value))
310 }
311 }
312313/// Returns the value as a primitive type.
314 ///
315 /// A call to this function will output a hint to the compiler that the value is in
316 /// range. In general this will help the optimizer to generate better code, but in edge
317 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
318#[doc = concat!("use [`", stringify!($type), "::get_without_hint`].")]
319 #[track_caller]
320 #[inline(always)]
321pub const fn get(self) -> $internal {
322const { assert!(MIN <= MAX); }
323// Safety: A stored value is always in range.
324unsafe { assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX) };
325*self.0.get()
326 }
327328/// Returns the value as a primitive type.
329 ///
330#[doc = concat!("The returned value is identical to [`", stringify!($type), "::get`].")]
331/// Unlike `get`, no hints are output to the compiler indicating the range that the
332 /// value is in. Depending on the scenario, this may with be helpful or harmful to
333 /// optimization.
334#[inline(always)]
335pub const fn get_without_hint(self) -> $internal {
336const { assert!(MIN <= MAX); }
337*self.0.get()
338 }
339340#[track_caller]
341 #[inline(always)]
342pub(crate) const fn get_ref(&self) -> &$internal {
343const { assert!(MIN <= MAX); }
344let value = self.0.get();
345// Safety: A stored value is always in range.
346unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
347 value
348 }
349350/// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
351#[inline(always)]
352pub const fn new(value: $internal) -> Option<Self> {
353const { assert!(MIN <= MAX); }
354if value < MIN || value > MAX {
355None
356} else {
357// Safety: The value is in range.
358Some(unsafe { Self::new_unchecked(value) })
359 }
360 }
361362/// Creates a ranged integer with a statically known value. **Fails to compile** if the
363 /// value is not in range.
364#[inline(always)]
365pub const fn new_static<const VALUE: $internal>() -> Self {
366const {
367assert!(MIN <= VALUE);
368assert!(VALUE <= MAX);
369 }
370// Safety: The value is in range.
371unsafe { Self::new_unchecked(VALUE) }
372 }
373374/// Creates a ranged integer with the given value, saturating if it is out of range.
375#[inline]
376pub const fn new_saturating(value: $internal) -> Self {
377const { assert!(MIN <= MAX); }
378if value < MIN {
379Self::MIN
380 } else if value > MAX {
381Self::MAX
382 } else {
383// Safety: The value is in range.
384unsafe { Self::new_unchecked(value) }
385 }
386 }
387388/// Emit a hint to the compiler that the value is in range.
389 ///
390 /// In some situations, this can help the optimizer to generate better code. In edge
391 /// cases this may lead to **worse** code generation. If you are unsure whether this is
392 /// helpful, harmful, or neutral, you should use [`cargo-show-asm`] to compare the
393 /// generated assembly.
394 ///
395 /// Aside from potentially affecting optimization, this function is a no-op.
396 ///
397 /// [`cargo-show-asm`]: https://crates.io/crates/cargo-show-asm
398#[inline(always)]
399pub const fn emit_range_hint(self) {
400const { assert!(MIN <= MAX); }
401let value = self.0.get();
402// Safety: A stored value is always in range.
403unsafe { assert_unchecked(MIN <= *value && *value <= MAX) };
404 }
405406/// Expand the range that the value may be in. **Fails to compile** if the new range is
407 /// not a superset of the current range.
408#[inline(always)]
409pub const fn expand<const NEW_MIN: $internal, const NEW_MAX: $internal>(
410self,
411 ) -> $type<NEW_MIN, NEW_MAX> {
412const {
413assert!(MIN <= MAX);
414assert!(NEW_MIN <= NEW_MAX);
415assert!(NEW_MIN <= MIN);
416assert!(NEW_MAX >= MAX);
417 }
418// Safety: The range is widened.
419unsafe { $type::new_unchecked(self.get()) }
420 }
421422/// Attempt to narrow the range that the value may be in. Returns `None` if the value
423 /// is outside the new range. **Fails to compile** if the new range is not a subset of
424 /// the current range.
425#[inline(always)]
426pub const fn narrow<
427const NEW_MIN: $internal,
428const NEW_MAX: $internal,
429 >(self) -> Option<$type<NEW_MIN, NEW_MAX>> {
430const {
431assert!(MIN <= MAX);
432assert!(NEW_MIN <= NEW_MAX);
433assert!(NEW_MIN >= MIN);
434assert!(NEW_MAX <= MAX);
435 }
436$type::<NEW_MIN, NEW_MAX>::new(self.get())
437 }
438439/// Narrow the range that the value may be in. **Fails to compile** if the new range is
440 /// not a subset of the current range.
441 ///
442 /// # Safety
443 ///
444 /// The value must in the range `NEW_MIN..=NEW_MAX`.
445#[inline(always)]
446pub const unsafe fn narrow_unchecked<
447const NEW_MIN: $internal,
448const NEW_MAX: $internal,
449 >(self) -> $type<NEW_MIN, NEW_MAX> {
450const {
451assert!(MIN <= MAX);
452assert!(NEW_MIN <= NEW_MAX);
453assert!(NEW_MIN >= MIN);
454assert!(NEW_MAX <= MAX);
455 }
456// Safety: The caller must ensure that the value is in the new range.
457unsafe { $type::new_unchecked(self.get()) }
458 }
459460/// Converts a string slice in a given base to an integer.
461 ///
462 /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
463 /// and trailing whitespace represent an error. Digits are a subset of these characters,
464 /// depending on `radix`:
465 ///
466 /// - `0-9`
467 /// - `a-z`
468 /// - `A-Z`
469 ///
470 /// # Panics
471 ///
472 /// Panics if `radix` is not in the range `2..=36`.
473 ///
474 /// # Examples
475 ///
476 /// Basic usage:
477 ///
478 /// ```rust
479#[doc = concat!("# use deranged::", stringify!($type), ";")]
480 #[doc = concat!(
481"assert_eq!(",
482stringify!($type),
483"::<5, 10>::from_str_radix(\"A\", 16), Ok(",
484stringify!($type),
485"::new_static::<10>()));",
486 )]
487/// ```
488#[inline]
489pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
490const { assert!(MIN <= MAX); }
491match $internal::from_str_radix(src, radix) {
492Ok(value) if value > MAX => {
493Err(ParseIntError { kind: IntErrorKind::PosOverflow })
494 }
495Ok(value) if value < MIN => {
496Err(ParseIntError { kind: IntErrorKind::NegOverflow })
497 }
498// Safety: If the value was out of range, it would have been caught in a
499 // previous arm.
500Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
501Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
502 }
503 }
504505/// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
506 /// value is out of range.
507#[must_use = "this returns the result of the operation, without modifying the original"]
508 #[inline]
509pub const fn checked_add(self, rhs: $internal) -> Option<Self> {
510const { assert!(MIN <= MAX); }
511Self::new(const_try_opt!(self.get().checked_add(rhs)))
512 }
513514/// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
515 /// range.
516 ///
517 /// # Safety
518 ///
519 /// The result of `self + rhs` must be in the range `MIN..=MAX`.
520#[must_use = "this returns the result of the operation, without modifying the original"]
521 #[track_caller]
522 #[inline(always)]
523pub const unsafe fn unchecked_add(self, rhs: $internal) -> Self {
524const { assert!(MIN <= MAX); }
525// Safety: The caller must ensure that the result is in range.
526unsafe {
527Self::new_unchecked(self.get().unchecked_add(rhs))
528 }
529 }
530531/// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
532 /// value is out of range.
533#[must_use = "this returns the result of the operation, without modifying the original"]
534 #[inline]
535pub const fn checked_sub(self, rhs: $internal) -> Option<Self> {
536const { assert!(MIN <= MAX); }
537Self::new(const_try_opt!(self.get().checked_sub(rhs)))
538 }
539540/// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
541 /// range.
542 ///
543 /// # Safety
544 ///
545 /// The result of `self - rhs` must be in the range `MIN..=MAX`.
546#[must_use = "this returns the result of the operation, without modifying the original"]
547 #[track_caller]
548 #[inline(always)]
549pub const unsafe fn unchecked_sub(self, rhs: $internal) -> Self {
550const { assert!(MIN <= MAX); }
551// Safety: The caller must ensure that the result is in range.
552unsafe {
553Self::new_unchecked(self.get().unchecked_sub(rhs))
554 }
555 }
556557/// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
558 /// value is out of range.
559#[must_use = "this returns the result of the operation, without modifying the original"]
560 #[inline]
561pub const fn checked_mul(self, rhs: $internal) -> Option<Self> {
562const { assert!(MIN <= MAX); }
563Self::new(const_try_opt!(self.get().checked_mul(rhs)))
564 }
565566/// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
567 /// in range.
568 ///
569 /// # Safety
570 ///
571 /// The result of `self * rhs` must be in the range `MIN..=MAX`.
572#[must_use = "this returns the result of the operation, without modifying the original"]
573 #[track_caller]
574 #[inline(always)]
575pub const unsafe fn unchecked_mul(self, rhs: $internal) -> Self {
576const { assert!(MIN <= MAX); }
577// Safety: The caller must ensure that the result is in range.
578unsafe {
579Self::new_unchecked(self.get().unchecked_mul(rhs))
580 }
581 }
582583/// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
584 /// if the resulting value is out of range.
585#[must_use = "this returns the result of the operation, without modifying the original"]
586 #[inline]
587pub const fn checked_div(self, rhs: $internal) -> Option<Self> {
588const { assert!(MIN <= MAX); }
589Self::new(const_try_opt!(self.get().checked_div(rhs)))
590 }
591592/// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
593 /// the result is in range.
594 ///
595 /// # Safety
596 ///
597 /// `self` must not be zero and the result of `self / rhs` must be in the range
598 /// `MIN..=MAX`.
599#[must_use = "this returns the result of the operation, without modifying the original"]
600 #[track_caller]
601 #[inline(always)]
602pub const unsafe fn unchecked_div(self, rhs: $internal) -> Self {
603const { assert!(MIN <= MAX); }
604// Safety: The caller must ensure that the result is in range and that `rhs` is not
605 // zero.
606unsafe {
607Self::new_unchecked(self.get().checked_div(rhs).unwrap_unchecked())
608 }
609 }
610611/// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
612 /// `rhs == 0` or if the resulting value is out of range.
613#[must_use = "this returns the result of the operation, without modifying the original"]
614 #[inline]
615pub const fn checked_div_euclid(self, rhs: $internal) -> Option<Self> {
616const { assert!(MIN <= MAX); }
617Self::new(const_try_opt!(self.get().checked_div_euclid(rhs)))
618 }
619620/// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
621 /// `rhs != 0` and that the result is in range.
622 ///
623 /// # Safety
624 ///
625 /// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
626 /// range `MIN..=MAX`.
627#[must_use = "this returns the result of the operation, without modifying the original"]
628 #[track_caller]
629 #[inline(always)]
630pub const unsafe fn unchecked_div_euclid(self, rhs: $internal) -> Self {
631const { assert!(MIN <= MAX); }
632// Safety: The caller must ensure that the result is in range and that `rhs` is not
633 // zero.
634unsafe {
635Self::new_unchecked(
636self.get().checked_div_euclid(rhs).unwrap_unchecked()
637 )
638 }
639 }
640641if_unsigned!($is_signed
642/// Remainder. Computes `self % rhs`, statically guaranteeing that the returned value
643 /// is in range.
644#[must_use = "this returns the result of the operation, without modifying the original"]
645 #[track_caller]
646 #[inline]
647pub const fn rem<const RHS_VALUE: $internal>(
648self,
649 rhs: $type<RHS_VALUE, RHS_VALUE>,
650 ) -> $type<0, RHS_VALUE> {
651const { assert!(MIN <= MAX); }
652// Safety: The result is guaranteed to be in range due to the nature of remainder on
653 // unsigned integers.
654unsafe { $type::new_unchecked(self.get() % rhs.get()) }
655 });
656657/// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
658 /// if the resulting value is out of range.
659#[must_use = "this returns the result of the operation, without modifying the original"]
660 #[inline]
661pub const fn checked_rem(self, rhs: $internal) -> Option<Self> {
662const { assert!(MIN <= MAX); }
663Self::new(const_try_opt!(self.get().checked_rem(rhs)))
664 }
665666/// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
667 /// result is in range.
668 ///
669 /// # Safety
670 ///
671 /// `self` must not be zero and the result of `self % rhs` must be in the range
672 /// `MIN..=MAX`.
673#[must_use = "this returns the result of the operation, without modifying the original"]
674 #[track_caller]
675 #[inline(always)]
676pub const unsafe fn unchecked_rem(self, rhs: $internal) -> Self {
677const { assert!(MIN <= MAX); }
678// Safety: The caller must ensure that the result is in range and that `rhs` is not
679 // zero.
680unsafe {
681Self::new_unchecked(self.get().checked_rem(rhs).unwrap_unchecked())
682 }
683 }
684685/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
686 /// `rhs == 0` or if the resulting value is out of range.
687#[must_use = "this returns the result of the operation, without modifying the original"]
688 #[inline]
689pub const fn checked_rem_euclid(self, rhs: $internal) -> Option<Self> {
690const { assert!(MIN <= MAX); }
691Self::new(const_try_opt!(self.get().checked_rem_euclid(rhs)))
692 }
693694/// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
695 /// `rhs != 0` and that the result is in range.
696 ///
697 /// # Safety
698 ///
699 /// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
700 /// range `MIN..=MAX`.
701#[must_use = "this returns the result of the operation, without modifying the original"]
702 #[track_caller]
703 #[inline(always)]
704pub const unsafe fn unchecked_rem_euclid(self, rhs: $internal) -> Self {
705const { assert!(MIN <= MAX); }
706// Safety: The caller must ensure that the result is in range and that `rhs` is not
707 // zero.
708unsafe {
709Self::new_unchecked(
710self.get().checked_rem_euclid(rhs).unwrap_unchecked()
711 )
712 }
713 }
714715/// Checked negation. Computes `-self`, returning `None` if the resulting value is out
716 /// of range.
717#[must_use = "this returns the result of the operation, without modifying the original"]
718 #[inline]
719pub const fn checked_neg(self) -> Option<Self> {
720const { assert!(MIN <= MAX); }
721Self::new(const_try_opt!(self.get().checked_neg()))
722 }
723724/// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
725 ///
726 /// # Safety
727 ///
728 /// The result of `-self` must be in the range `MIN..=MAX`.
729#[must_use = "this returns the result of the operation, without modifying the original"]
730 #[track_caller]
731 #[inline(always)]
732pub const unsafe fn unchecked_neg(self) -> Self {
733const { assert!(MIN <= MAX); }
734// Safety: The caller must ensure that the result is in range.
735 // TODO(MSRV 1.93) use `unchecked_neg`
736unsafe { Self::new_unchecked(self.get().checked_neg().unwrap_unchecked()) }
737 }
738739/// Negation. Computes `self.neg()`, **failing to compile** if the result is not
740 /// guaranteed to be in range.
741#[must_use = "this returns the result of the operation, without modifying the original"]
742 #[inline(always)]
743pub const fn neg(self) -> Self {
744const {
745assert!(MIN <= MAX);
746if_signed! { $is_signed
747assert!(MIN != $internal::MIN);
748assert!(-MIN <= MAX);
749assert!(-MAX >= MIN);
750 }
751if_unsigned! { $is_signed
752assert!(MAX == 0);
753 }
754 }
755// Safety: The compiler asserts that the result is in range.
756unsafe { self.unchecked_neg() }
757 }
758759/// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
760 /// is out of range.
761#[must_use = "this returns the result of the operation, without modifying the original"]
762 #[inline]
763pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
764const { assert!(MIN <= MAX); }
765Self::new(const_try_opt!(self.get().checked_shl(rhs)))
766 }
767768/// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
769 ///
770 /// # Safety
771 ///
772 /// The result of `self << rhs` must be in the range `MIN..=MAX`.
773#[must_use = "this returns the result of the operation, without modifying the original"]
774 #[track_caller]
775 #[inline(always)]
776pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
777const { assert!(MIN <= MAX); }
778// Safety: The caller must ensure that the result is in range.
779unsafe {
780// TOD(MSRV 1.93) use `unchecked_shl`
781Self::new_unchecked(self.get().checked_shl(rhs).unwrap_unchecked())
782 }
783 }
784785/// Checked shift right. Computes `self >> rhs`, returning `None` if
786 /// the resulting value is out of range.
787#[must_use = "this returns the result of the operation, without modifying the original"]
788 #[inline]
789pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
790const { assert!(MIN <= MAX); }
791Self::new(const_try_opt!(self.get().checked_shr(rhs)))
792 }
793794/// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
795 ///
796 /// # Safety
797 ///
798 /// The result of `self >> rhs` must be in the range `MIN..=MAX`.
799#[must_use = "this returns the result of the operation, without modifying the original"]
800 #[track_caller]
801 #[inline(always)]
802pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
803const { assert!(MIN <= MAX); }
804// Safety: The caller must ensure that the result is in range.
805unsafe {
806// TODO(MSRV 1.93) use `unchecked_shr`
807Self::new_unchecked(self.get().checked_shr(rhs).unwrap_unchecked())
808 }
809 }
810811if_signed!($is_signed
812/// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
813 /// value is out of range.
814#[must_use = "this returns the result of the operation, without modifying the original"]
815 #[inline]
816pub const fn checked_abs(self) -> Option<Self> {
817const { assert!(MIN <= MAX); }
818Self::new(const_try_opt!(self.get().checked_abs()))
819 }
820821/// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
822 /// range.
823 ///
824 /// # Safety
825 ///
826 /// The result of `self.abs()` must be in the range `MIN..=MAX`.
827#[must_use = "this returns the result of the operation, without modifying the original"]
828 #[track_caller]
829 #[inline(always)]
830pub const unsafe fn unchecked_abs(self) -> Self {
831const { assert!(MIN <= MAX); }
832// Safety: The caller must ensure that the result is in range.
833unsafe { Self::new_unchecked(self.get().checked_abs().unwrap_unchecked()) }
834 }
835836/// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
837 /// guaranteed to be in range.
838#[must_use = "this returns the result of the operation, without modifying the original"]
839 #[inline(always)]
840pub const fn abs(self) -> Self {
841const {
842assert!(MIN <= MAX);
843assert!(MIN != $internal::MIN);
844assert!(-MIN <= MAX);
845 }
846// <Self as $crate::traits::AbsIsSafe>::ASSERT;
847 // Safety: The compiler asserts that the result is in range.
848unsafe { self.unchecked_abs() }
849 });
850851/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
852 /// value is out of range.
853#[must_use = "this returns the result of the operation, without modifying the original"]
854 #[inline]
855pub const fn checked_pow(self, exp: u32) -> Option<Self> {
856const { assert!(MIN <= MAX); }
857Self::new(const_try_opt!(self.get().checked_pow(exp)))
858 }
859860/// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
861 /// range.
862 ///
863 /// # Safety
864 ///
865 /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
866#[must_use = "this returns the result of the operation, without modifying the original"]
867 #[track_caller]
868 #[inline(always)]
869pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
870const { assert!(MIN <= MAX); }
871// Safety: The caller must ensure that the result is in range.
872unsafe {
873Self::new_unchecked(self.get().checked_pow(exp).unwrap_unchecked())
874 }
875 }
876877/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
878 /// bounds.
879#[must_use = "this returns the result of the operation, without modifying the original"]
880 #[inline]
881pub const fn saturating_add(self, rhs: $internal) -> Self {
882const { assert!(MIN <= MAX); }
883Self::new_saturating(self.get().saturating_add(rhs))
884 }
885886/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
887 /// bounds.
888#[must_use = "this returns the result of the operation, without modifying the original"]
889 #[inline]
890pub const fn saturating_sub(self, rhs: $internal) -> Self {
891const { assert!(MIN <= MAX); }
892Self::new_saturating(self.get().saturating_sub(rhs))
893 }
894895if_signed!($is_signed
896/// Saturating integer negation. Computes `self - rhs`, saturating at the numeric
897 /// bounds.
898#[must_use = "this returns the result of the operation, without modifying the original"]
899 #[inline]
900pub const fn saturating_neg(self) -> Self {
901const { assert!(MIN <= MAX); }
902Self::new_saturating(self.get().saturating_neg())
903 });
904905if_signed!($is_signed
906/// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
907#[must_use = "this returns the result of the operation, without modifying the original"]
908 #[inline]
909pub const fn saturating_abs(self) -> Self {
910const { assert!(MIN <= MAX); }
911Self::new_saturating(self.get().saturating_abs())
912 });
913914/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
915 /// bounds.
916#[must_use = "this returns the result of the operation, without modifying the original"]
917 #[inline]
918pub const fn saturating_mul(self, rhs: $internal) -> Self {
919const { assert!(MIN <= MAX); }
920Self::new_saturating(self.get().saturating_mul(rhs))
921 }
922923/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
924 /// numeric bounds.
925#[must_use = "this returns the result of the operation, without modifying the original"]
926 #[inline]
927pub const fn saturating_pow(self, exp: u32) -> Self {
928const { assert!(MIN <= MAX); }
929Self::new_saturating(self.get().saturating_pow(exp))
930 }
931932if_signed! { $is_signed
933/// Returns `true` if the number is positive and `false` if the number is zero or
934 /// negative.
935#[inline]
936pub const fn is_positive(self) -> bool {
937const { assert!(MIN <= MAX); }
938self.get().is_positive()
939 }
940941/// Returns `true` if the number is negative and `false` if the number is zero or
942 /// positive.
943#[inline]
944pub const fn is_negative(self) -> bool {
945const { assert!(MIN <= MAX); }
946self.get().is_negative()
947 }
948 }
949950/// Compute the `rem_euclid` of this type with its unsigned type equivalent
951// Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
952 // Also because this isn't implemented for normal types in std.
953#[must_use = "this returns the result of the operation, without modifying the original"]
954 #[track_caller]
955 #[inline]
956 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
957const fn rem_euclid_unsigned(
958 rhs: $internal,
959 range_len: $unsigned_type
960) -> $unsigned_type {
961#[allow(unused_comparisons)]
962if rhs >= 0 {
963 (rhs as $unsigned_type) % range_len
964 } else {
965// Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
966 // Can't write -ux or ux::abs() method. This gets around compilation error.
967 // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
968let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
969// Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
970 // Also = 0 in mod range_len arithmetic.
971 // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
972 // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
973 // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
974 // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
975((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
976 }
977 }
978979/// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
980 /// bounds.
981#[must_use = "this returns the result of the operation, without modifying the original"]
982 #[inline]
983 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
984pub const fn wrapping_add(self, rhs: $internal) -> Self {
985const { assert!(MIN <= MAX); }
986// Forward to internal type's impl if same as type.
987if MIN == $internal::MIN && MAX == $internal::MAX {
988// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
989return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
990 }
991992let inner = self.get();
993994// Won't overflow because of std impl forwarding.
995let range_len = MAX.abs_diff(MIN) + 1;
996997// Calculate the offset with proper handling for negative rhs
998let offset = Self::rem_euclid_unsigned(rhs, range_len);
9991000let greater_vals = MAX.abs_diff(inner);
1001// No wrap
1002if offset <= greater_vals {
1003// Safety:
1004 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1005 // if inner < 0: Same as >=0 with caveat:
1006 // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
1007 // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
1008 // (the difference doesn't matter since it won't overflow),
1009 // but unsigned integers don't have either method so it won't compile that way.
1010unsafe { Self::new_unchecked(
1011 ((inner as $unsigned_type).wrapping_add(offset)) as $internal
1012) }
1013 }
1014// Wrap
1015else {
1016// Safety:
1017 // - offset < range_len by rem_euclid (MIN + ... safe)
1018 // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
1019 //
1020 // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
1021unsafe { Self::new_unchecked(
1022 ((MIN as $unsigned_type).wrapping_add(
1023 offset - (greater_vals + 1)
1024 )) as $internal
1025) }
1026 }
1027 }
10281029/// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
1030 /// bounds.
1031#[must_use = "this returns the result of the operation, without modifying the original"]
1032 #[inline]
1033 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
1034pub const fn wrapping_sub(self, rhs: $internal) -> Self {
1035const { assert!(MIN <= MAX); }
1036// Forward to internal type's impl if same as type.
1037if MIN == $internal::MIN && MAX == $internal::MAX {
1038// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1039return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
1040 }
10411042let inner = self.get();
10431044// Won't overflow because of std impl forwarding.
1045let range_len = MAX.abs_diff(MIN) + 1;
10461047// Calculate the offset with proper handling for negative rhs
1048let offset = Self::rem_euclid_unsigned(rhs, range_len);
10491050let lesser_vals = MIN.abs_diff(inner);
1051// No wrap
1052if offset <= lesser_vals {
1053// Safety:
1054 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1055 // if inner < 0: Same as >=0 with caveat:
1056 // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
1057 // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
1058 // (the difference doesn't matter since it won't overflow below 0),
1059 // but unsigned integers don't have either method so it won't compile that way.
1060unsafe { Self::new_unchecked(
1061 ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
1062) }
1063 }
1064// Wrap
1065else {
1066// Safety:
1067 // - offset < range_len by rem_euclid (MAX - ... safe)
1068 // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
1069 //
1070 // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
1071unsafe { Self::new_unchecked(
1072 ((MAX as $unsigned_type).wrapping_sub(
1073 offset - (lesser_vals + 1)
1074 )) as $internal
1075) }
1076 }
1077 }
1078 }
10791080impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
1081/// The value used as the niche. Must not be in the range `MIN..=MAX`.
1082const NICHE: $internal = match (MIN, MAX) {
1083 ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
1084 ($internal::MIN, _) => $internal::MAX,
1085 (_, _) => $internal::MIN,
1086 };
10871088/// An optional ranged value that is not present.
1089#[allow(non_upper_case_globals)]
1090pub const None: Self = Self(Self::NICHE);
10911092/// Creates an optional ranged value that is present.
1093#[allow(non_snake_case)]
1094 #[inline(always)]
1095pub const fn Some(value: $type<MIN, MAX>) -> Self {
1096const { assert!(MIN <= MAX); }
1097Self(value.get())
1098 }
10991100/// Returns the value as the standard library's [`Option`] type.
1101#[inline(always)]
1102pub const fn get(self) -> Option<$type<MIN, MAX>> {
1103const { assert!(MIN <= MAX); }
1104if self.0 == Self::NICHE {
1105None
1106} else {
1107// Safety: A stored value that is not the niche is always in range.
1108Some(unsafe { $type::new_unchecked(self.0) })
1109 }
1110 }
11111112/// Creates an optional ranged integer without checking the value.
1113 ///
1114 /// # Safety
1115 ///
1116 /// The value must be within the range `MIN..=MAX`. As the value used for niche
1117 /// value optimization is unspecified, the provided value must not be the niche
1118 /// value.
1119#[inline(always)]
1120 #[track_caller]
1121pub const unsafe fn some_unchecked(value: $internal) -> Self {
1122const { assert!(MIN <= MAX); }
1123// Safety: The caller must ensure that the value is in range.
1124unsafe { assert_unchecked(MIN <= value && value <= MAX) };
1125Self(value)
1126 }
11271128/// Obtain the inner value of the struct. This is useful for comparisons.
1129#[inline(always)]
1130pub(crate) const fn inner(self) -> $internal {
1131const { assert!(MIN <= MAX); }
1132self.0
1133}
11341135/// Obtain the value of the struct as an `Option` of the primitive type.
1136 ///
1137 /// A call to this function will output a hint to the compiler that the value is in
1138 /// range. In general this will help the optimizer to generate better code, but in edge
1139 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
1140#[doc = concat!(
1141"use [`", stringify!($optional_type), "::get_primitive_without_hint`]."
1142)]
1143 #[inline(always)]
1144pub const fn get_primitive(self) -> Option<$internal> {
1145const { assert!(MIN <= MAX); }
1146Some(const_try_opt!(self.get()).get())
1147 }
11481149/// Obtain the value of the struct as an `Option` of the primitive type.
1150 ///
1151#[doc = concat!(
1152"The returned value is identical to [`", stringify!($optional_type), "::",
1153"get_primitive`]."
1154)]
1155/// Unlike `get_primitive`, no hints are output to the compiler indicating the range
1156 /// that the value is in. Depending on the scenario, this may with be helpful or harmful
1157 /// to optimization.
1158#[inline(always)]
1159pub const fn get_primitive_without_hint(self) -> Option<$internal> {
1160const { assert!(MIN <= MAX); }
1161Some(const_try_opt!(self.get()).get_without_hint())
1162 }
11631164/// Returns `true` if the value is the niche value.
1165#[inline(always)]
1166pub const fn is_none(&self) -> bool {
1167const { assert!(MIN <= MAX); }
1168self.get().is_none()
1169 }
11701171/// Returns `true` if the value is not the niche value.
1172#[inline(always)]
1173pub const fn is_some(&self) -> bool {
1174const { assert!(MIN <= MAX); }
1175self.get().is_some()
1176 }
1177 }
11781179impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
1180#[inline(always)]
1181fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1182const { assert!(MIN <= MAX); }
1183self.get().fmt(f)
1184 }
1185 }
11861187impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
1188#[inline(always)]
1189fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1190const { assert!(MIN <= MAX); }
1191self.get().fmt(f)
1192 }
1193 }
11941195impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
1196#[inline(always)]
1197fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1198const { assert!(MIN <= MAX); }
1199self.get().fmt(f)
1200 }
1201 }
12021203#[cfg(feature = "powerfmt")]
1204impl<
1205const MIN: $internal,
1206const MAX: $internal,
1207 > smart_display::SmartDisplay for $type<MIN, MAX> {
1208type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
12091210#[inline(always)]
1211fn metadata(
1212&self,
1213 f: smart_display::FormatterOptions,
1214 ) -> smart_display::Metadata<'_, Self> {
1215const { assert!(MIN <= MAX); }
1216self.get_ref().metadata(f).reuse()
1217 }
12181219#[inline(always)]
1220fn fmt_with_metadata(
1221&self,
1222 f: &mut fmt::Formatter<'_>,
1223 metadata: smart_display::Metadata<'_, Self>,
1224 ) -> fmt::Result {
1225const { assert!(MIN <= MAX); }
1226self.get().fmt_with_metadata(f, metadata.reuse())
1227 }
1228 }
12291230impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
1231#[inline(always)]
1232fn default() -> Self {
1233const { assert!(MIN <= MAX); }
1234Self::None
1235 }
1236 }
12371238impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
1239#[inline(always)]
1240fn as_ref(&self) -> &$internal {
1241const { assert!(MIN <= MAX); }
1242&self.get_ref()
1243 }
1244 }
12451246impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
1247#[inline(always)]
1248fn borrow(&self) -> &$internal {
1249const { assert!(MIN <= MAX); }
1250&self.get_ref()
1251 }
1252 }
12531254impl<
1255const MIN_A: $internal,
1256const MAX_A: $internal,
1257const MIN_B: $internal,
1258const MAX_B: $internal,
1259 > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1260#[inline(always)]
1261fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
1262const {
1263assert!(MIN_A <= MAX_A);
1264assert!(MIN_B <= MAX_B);
1265 }
1266self.get() == other.get()
1267 }
1268 }
12691270impl<
1271const MIN_A: $internal,
1272const MAX_A: $internal,
1273const MIN_B: $internal,
1274const MAX_B: $internal,
1275 > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1276#[inline(always)]
1277fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
1278const {
1279assert!(MIN_A <= MAX_A);
1280assert!(MIN_B <= MAX_B);
1281 }
1282self.inner() == other.inner()
1283 }
1284 }
12851286impl<
1287const MIN_A: $internal,
1288const MAX_A: $internal,
1289const MIN_B: $internal,
1290const MAX_B: $internal,
1291 > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1292#[inline(always)]
1293fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
1294const {
1295assert!(MIN_A <= MAX_A);
1296assert!(MIN_B <= MAX_B);
1297 }
1298self.get().partial_cmp(&other.get())
1299 }
1300 }
13011302impl<
1303const MIN_A: $internal,
1304const MAX_A: $internal,
1305const MIN_B: $internal,
1306const MAX_B: $internal,
1307 > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1308#[inline]
1309fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
1310const {
1311assert!(MIN_A <= MAX_A);
1312assert!(MIN_B <= MAX_B);
1313 }
1314if self.is_none() && other.is_none() {
1315Some(Ordering::Equal)
1316 } else if self.is_none() {
1317Some(Ordering::Less)
1318 } else if other.is_none() {
1319Some(Ordering::Greater)
1320 } else {
1321self.inner().partial_cmp(&other.inner())
1322 }
1323 }
1324 }
13251326impl<
1327const MIN: $internal,
1328const MAX: $internal,
1329 > Ord for $optional_type<MIN, MAX> {
1330#[inline]
1331fn cmp(&self, other: &Self) -> Ordering {
1332const { assert!(MIN <= MAX); }
1333if self.is_none() && other.is_none() {
1334 Ordering::Equal
1335 } else if self.is_none() {
1336 Ordering::Less
1337 } else if other.is_none() {
1338 Ordering::Greater
1339 } else {
1340self.inner().cmp(&other.inner())
1341 }
1342 }
1343 }
13441345impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
1346#[inline(always)]
1347fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1348const { assert!(MIN <= MAX); }
1349self.get().fmt(f)
1350 }
1351 }
13521353impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
1354#[inline(always)]
1355fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1356const { assert!(MIN <= MAX); }
1357self.get().fmt(f)
1358 }
1359 }
13601361impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
1362#[inline(always)]
1363fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1364const { assert!(MIN <= MAX); }
1365self.get().fmt(f)
1366 }
1367 }
13681369impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
1370#[inline(always)]
1371fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1372const { assert!(MIN <= MAX); }
1373self.get().fmt(f)
1374 }
1375 }
13761377impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
1378#[inline(always)]
1379fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1380const { assert!(MIN <= MAX); }
1381self.get().fmt(f)
1382 }
1383 }
13841385impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
1386#[inline(always)]
1387fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1388const { assert!(MIN <= MAX); }
1389self.get().fmt(f)
1390 }
1391 }
13921393if_unsigned! { $is_signed
1394impl From<NonZero<$internal>> for $type<1, { $internal::MAX }> {
1395#[inline(always)]
1396fn from(value: NonZero<$internal>) -> Self {
1397Self::from_nonzero(value)
1398 }
1399 }
14001401impl From<$type<1, { $internal::MAX }>> for NonZero<$internal> {
1402#[inline(always)]
1403fn from(value: $type<1, { $internal::MAX }>) -> Self {
1404 value.to_nonzero()
1405 }
1406 }
1407 }
14081409impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
1410#[inline(always)]
1411fn from(value: $type<MIN, MAX>) -> Self {
1412const { assert!(MIN <= MAX); }
1413 value.get()
1414 }
1415 }
14161417impl<
1418const MIN: $internal,
1419const MAX: $internal,
1420 > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
1421#[inline(always)]
1422fn from(value: $type<MIN, MAX>) -> Self {
1423const { assert!(MIN <= MAX); }
1424Self::Some(value)
1425 }
1426 }
14271428impl<
1429const MIN: $internal,
1430const MAX: $internal,
1431 > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
1432#[inline(always)]
1433fn from(value: Option<$type<MIN, MAX>>) -> Self {
1434const { assert!(MIN <= MAX); }
1435match value {
1436Some(value) => Self::Some(value),
1437None => Self::None,
1438 }
1439 }
1440 }
14411442impl<
1443const MIN: $internal,
1444const MAX: $internal,
1445 > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
1446#[inline(always)]
1447fn from(value: $optional_type<MIN, MAX>) -> Self {
1448const { assert!(MIN <= MAX); }
1449 value.get()
1450 }
1451 }
14521453impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
1454type Error = TryFromIntError;
14551456#[inline]
1457fn try_from(value: $internal) -> Result<Self, Self::Error> {
1458const { assert!(MIN <= MAX); }
1459Self::new(value).ok_or(TryFromIntError)
1460 }
1461 }
14621463impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
1464type Err = ParseIntError;
14651466#[inline]
1467fn from_str(s: &str) -> Result<Self, Self::Err> {
1468const { assert!(MIN <= MAX); }
1469let value = s.parse::<$internal>().map_err(|e| ParseIntError {
1470 kind: e.kind().clone()
1471 })?;
1472if value < MIN {
1473Err(ParseIntError { kind: IntErrorKind::NegOverflow })
1474 } else if value > MAX {
1475Err(ParseIntError { kind: IntErrorKind::PosOverflow })
1476 } else {
1477// Safety: The value was previously checked for validity.
1478Ok(unsafe { Self::new_unchecked(value) })
1479 }
1480 }
1481 }
14821483 $(impl<
1484const MIN_SRC: $from_internal,
1485const MAX_SRC: $from_internal,
1486const MIN_DST: $internal,
1487const MAX_DST: $internal,
1488 > From<$from<MIN_SRC, MAX_SRC>> for $type<MIN_DST, MAX_DST>
1489 {
1490#[inline(always)]
1491 #[allow(trivial_numeric_casts, unused_comparisons)]
1492fn from(value: $from<MIN_SRC, MAX_SRC>) -> Self {
1493const {
1494assert!(MIN_SRC <= MAX_SRC, "source range is invalid");
1495assert!(MIN_DST <= MAX_DST, "target range is invalid");
14961497match ($from_internal::MIN == 0, $internal::MIN == 0) {
1498// unsigned -> unsigned
1499(true, true) => {
1500assert!(
1501 MIN_SRC as u128 >= MIN_DST as u128,
1502"minimum value cannot be represented in the target range"
1503);
1504assert!(
1505 MAX_SRC as u128 <= MAX_DST as u128,
1506"maximum value cannot be represented in the target range"
1507);
1508 }
1509// signed -> signed
1510(false, false) => {
1511assert!(
1512 MIN_SRC as i128 >= MIN_DST as i128,
1513"minimum value cannot be represented in the target range"
1514);
1515assert!(
1516 MAX_SRC as i128 <= MAX_DST as i128,
1517"maximum value cannot be represented in the target range"
1518);
1519 }
1520// unsigned -> signed
1521(true, false) => {
1522assert!(
1523 MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128,
1524"minimum value cannot be represented in the target range"
1525);
1526assert!(
1527 MAX_DST >= 0
1528&& MAX_SRC as u128 <= i128::MAX as u128
1529 && MAX_SRC as i128 <= MAX_DST as i128,
1530"maximum value cannot be represented in the target range"
1531);
1532 }
1533// signed -> unsigned
1534(false, true) => {
1535assert!(
1536 MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128,
1537"minimum value cannot be represented in the target range"
1538);
1539assert!(
1540 MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128,
1541"maximum value cannot be represented in the target range"
1542);
1543 }
1544 }
1545 }
15461547// Safety: The source range is a subset of the destination range.
1548unsafe { $type::new_unchecked(value.get() as $internal) }
1549 }
1550 })+
15511552#[cfg(feature = "serde")]
1553impl<const MIN: $internal, const MAX: $internal> serde_core::Serialize for $type<MIN, MAX> {
1554#[inline(always)]
1555fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1556 {
1557const { assert!(MIN <= MAX); }
1558self.get().serialize(serializer)
1559 }
1560 }
15611562#[cfg(feature = "serde")]
1563impl<
1564const MIN: $internal,
1565const MAX: $internal,
1566 > serde_core::Serialize for $optional_type<MIN, MAX> {
1567#[inline(always)]
1568fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1569 {
1570const { assert!(MIN <= MAX); }
1571self.get().serialize(serializer)
1572 }
1573 }
15741575#[cfg(feature = "serde")]
1576impl<
1577'de,
1578const MIN: $internal,
1579const MAX: $internal,
1580 > serde_core::Deserialize<'de> for $type<MIN, MAX> {
1581#[inline]
1582fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1583 -> Result<Self, D::Error>
1584 {
1585const { assert!(MIN <= MAX); }
1586let internal = <$internal>::deserialize(deserializer)?;
1587Self::new(internal).ok_or_else(||
1588 <D::Error as serde_core::de::Error>::invalid_value(
1589 serde_core::de::Unexpected::Other("integer"),
1590#[cfg(feature = "alloc")] {
1591&alloc::format!("an integer in the range {}..={}", MIN, MAX).as_ref()
1592 },
1593#[cfg(not(feature = "alloc"))] {
1594&"an integer in the valid range"
1595}
1596 )
1597 )
1598 }
1599 }
16001601#[cfg(feature = "serde")]
1602impl<
1603'de,
1604const MIN: $internal,
1605const MAX: $internal,
1606 > serde_core::Deserialize<'de> for $optional_type<MIN, MAX> {
1607#[inline]
1608fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1609 -> Result<Self, D::Error>
1610 {
1611const { assert!(MIN <= MAX); }
1612Ok(Self::Some($type::<MIN, MAX>::deserialize(deserializer)?))
1613 }
1614 }
16151616#[cfg(feature = "rand08")]
1617impl<
1618const MIN: $internal,
1619const MAX: $internal,
1620 > rand08::distributions::Distribution<$type<MIN, MAX>> for rand08::distributions::Standard {
1621#[inline]
1622fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1623const { assert!(MIN <= MAX); }
1624$type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1625 }
1626 }
16271628if_not_manual_rand_09! {
1629 [$($($skips)+)?]
1630#[cfg(feature = "rand09")]
1631impl<
1632const MIN: $internal,
1633const MAX: $internal,
1634 > rand09::distr::Distribution<$type<MIN, MAX>> for rand09::distr::StandardUniform {
1635#[inline]
1636fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1637const { assert!(MIN <= MAX); }
1638$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1639 }
1640 }
1641 }
16421643if_not_manual_rand_010! {
1644 [$($($skips)+)?]
1645#[cfg(feature = "rand010")]
1646impl<
1647const MIN: $internal,
1648const MAX: $internal,
1649 > rand010::distr::Distribution<$type<MIN, MAX>> for rand010::distr::StandardUniform {
1650#[inline]
1651fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1652const { assert!(MIN <= MAX); }
1653use rand010::RngExt as _;
1654$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1655 }
1656 }
1657 }
16581659#[cfg(feature = "rand08")]
1660impl<
1661const MIN: $internal,
1662const MAX: $internal,
1663 > rand08::distributions::Distribution<$optional_type<MIN, MAX>>
1664for rand08::distributions::Standard {
1665#[inline]
1666fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1667const { assert!(MIN <= MAX); }
1668 rng.r#gen::<Option<$type<MIN, MAX>>>().into()
1669 }
1670 }
16711672#[cfg(feature = "rand09")]
1673impl<
1674const MIN: $internal,
1675const MAX: $internal,
1676 > rand09::distr::Distribution<$optional_type<MIN, MAX>>
1677for rand09::distr::StandardUniform {
1678#[inline]
1679fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1680const { assert!(MIN <= MAX); }
1681if rng.random() {
1682$optional_type::None
1683} else {
1684$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1685 }
1686 }
1687 }
16881689#[cfg(feature = "rand010")]
1690impl<
1691const MIN: $internal,
1692const MAX: $internal,
1693 > rand010::distr::Distribution<$optional_type<MIN, MAX>>
1694for rand010::distr::StandardUniform {
1695#[inline]
1696fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1697const { assert!(MIN <= MAX); }
1698use rand010::RngExt as _;
1699if rng.random() {
1700$optional_type::None
1701} else {
1702$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1703 }
1704 }
1705 }
17061707#[cfg(feature = "num")]
1708impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
1709#[inline(always)]
1710fn min_value() -> Self {
1711const { assert!(MIN <= MAX); }
1712Self::MIN
1713 }
17141715#[inline(always)]
1716fn max_value() -> Self {
1717const { assert!(MIN <= MAX); }
1718Self::MAX
1719 }
1720 }
17211722#[cfg(feature = "quickcheck")]
1723impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
1724#[inline]
1725fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1726const { assert!(MIN <= MAX); }
1727// Safety: The `rem_euclid` call and addition ensure that the value is in range.
1728unsafe {
1729Self::new_unchecked($internal::arbitrary(g).rem_euclid(MAX - MIN + 1) + MIN)
1730 }
1731 }
17321733#[inline]
1734fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1735 ::alloc::boxed::Box::new(
1736self.get()
1737 .shrink()
1738 .filter_map(Self::new)
1739 )
1740 }
1741 }
17421743#[cfg(feature = "quickcheck")]
1744impl<
1745const MIN: $internal,
1746const MAX: $internal,
1747 > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
1748#[inline]
1749fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1750const { assert!(MIN <= MAX); }
1751 Option::<$type<MIN, MAX>>::arbitrary(g).into()
1752 }
17531754#[inline]
1755fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1756 ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
1757 }
1758 }
1759 )*};
1760}
17611762#[doc = "Equivalent to `RangedIsize`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type risize<const MIN : isize, const MAX : isize> = RangedIsize<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedIsize`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_risize<const MIN : isize, const MAX : isize> =
OptionRangedIsize<MIN, MAX>;
#[doc = "An `isize` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedIsize<const MIN : isize, const MAX : isize>(Unsafe<isize>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : isize, const MAX : isize> ::core::clone::TrivialClone
for RangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::clone::Clone for
RangedIsize<MIN, MAX> {
#[inline]
fn clone(&self) -> RangedIsize<MIN, MAX> {
let _: ::core::clone::AssertParamIsClone<Unsafe<isize>>;
*self
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::marker::Copy for
RangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Eq for
RangedIsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<isize>>;
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Ord for
RangedIsize<MIN, MAX> {
#[inline]
fn cmp(&self, other: &RangedIsize<MIN, MAX>) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::hash::Hash for
RangedIsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedIsize`; similar to `Option<RangedIsize>` with better optimization."]
///
#[doc =
"If `MIN` is [`isize::MIN`] _and_ `MAX` is [`isize::MAX`] then compilation will fail. This is because there is no way to represent the niche value."]
///
/// This type is useful when you need to store an optional ranged value in a struct, but
/// do not want the overhead of an `Option` type. This reduces the size of the struct
/// overall, and is particularly useful when you have a large number of optional fields.
/// Note that most operations must still be performed on the [`Option`] type, which is
#[doc = "obtained with [`OptionRangedIsize::get`]."]
#[repr(transparent)]
pub struct OptionRangedIsize<const MIN : isize, const MAX : isize>(isize);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : isize, const MAX : isize> ::core::clone::TrivialClone
for OptionRangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::clone::Clone for
OptionRangedIsize<MIN, MAX> {
#[inline]
fn clone(&self) -> OptionRangedIsize<MIN, MAX> {
let _: ::core::clone::AssertParamIsClone<isize>;
*self
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::marker::Copy for
OptionRangedIsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::cmp::Eq for
OptionRangedIsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<isize>;
}
}
#[automatically_derived]
impl<const MIN : isize, const MAX : isize> ::core::hash::Hash for
OptionRangedIsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedIsize<0, 0> {
#[doc = "A RangedIsize that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : isize>() -> RangedIsize<VALUE, VALUE> {
unsafe { RangedIsize::new_unchecked(VALUE) }
}
}
impl<const MIN : isize, const MAX : isize> RangedIsize<MIN, MAX> {
/// The smallest value that can be represented by this type.
pub const MIN: Self = Self::new_static::<MIN>();
/// The largest value that can be represented by this type.
pub const MAX: Self = Self::new_static::<MAX>();
/// Creates a ranged integer without checking the value.
///
/// # Safety
///
/// The value must be within the range `MIN..=MAX`.
#[track_caller]
#[inline(always)]
pub const unsafe fn new_unchecked(value: isize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
assert_unchecked(MIN <= value && value <= MAX);
Self(Unsafe::new(value))
}
}
/// Returns the value as a primitive type.
///
/// A call to this function will output a hint to the compiler that the value is in
/// range. In general this will help the optimizer to generate better code, but in edge
/// cases this may lead to worse code generation. To avoid outputting the hint, you can
#[doc = "use [`RangedIsize::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> isize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX)
};
*self.0.get()
}
/// Returns the value as a primitive type.
///
#[doc = "The returned value is identical to [`RangedIsize::get`]."]
/// Unlike `get`, no hints are output to the compiler indicating the range that the
/// value is in. Depending on the scenario, this may with be helpful or harmful to
/// 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())
}
/// Narrow the range that the value may be in. **Fails to compile** if the new range is
/// not a subset of the current range.
///
/// # Safety
///
/// The value must in the range `NEW_MIN..=NEW_MAX`.
#[inline(always)]
pub const unsafe fn narrow_unchecked<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()) }
}
/// 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(self.get().unchecked_add(rhs)) }
}
/// 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(self.get().unchecked_sub(rhs)) }
}
/// 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(self.get().unchecked_mul(rhs)) }
}
/// 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(self.get().checked_div(rhs).unwrap_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(self.get().checked_div_euclid(rhs).unwrap_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(self.get().checked_rem(rhs).unwrap_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(self.get().checked_rem_euclid(rhs).unwrap_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(self.get().checked_neg().unwrap_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(self.get().checked_shl(rhs).unwrap_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(self.get().checked_shr(rhs).unwrap_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(self.get().checked_abs().unwrap_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(self.get().checked_pow(exp).unwrap_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
/// to 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! {
1763RangedU8 {
1764 mod_name: ranged_u8
1765 alias: ru81766 internal: u8
1767 signed: false
1768unsigned: u8
1769 optional: OptionRangedU81770 optional_alias: Option_ru81771 from: [
1772RangedU16(u16)
1773RangedU32(u32)
1774RangedU64(u64)
1775RangedU128(u128)
1776RangedUsize(usize)
1777RangedI8(i8)
1778RangedI16(i16)
1779RangedI32(i32)
1780RangedI64(i64)
1781RangedI128(i128)
1782RangedIsize(isize)
1783 ]
1784 }
1785RangedU16 {
1786 mod_name: ranged_u16
1787 alias: ru161788 internal: u16
1789 signed: false
1790unsigned: u16
1791 optional: OptionRangedU161792 optional_alias: Option_ru161793 from: [
1794RangedU8(u8)
1795RangedU32(u32)
1796RangedU64(u64)
1797RangedU128(u128)
1798RangedUsize(usize)
1799RangedI8(i8)
1800RangedI16(i16)
1801RangedI32(i32)
1802RangedI64(i64)
1803RangedI128(i128)
1804RangedIsize(isize)
1805 ]
1806 }
1807RangedU32 {
1808 mod_name: ranged_u32
1809 alias: ru321810 internal: u32
1811 signed: false
1812unsigned: u32
1813 optional: OptionRangedU321814 optional_alias: Option_ru321815 from: [
1816RangedU8(u8)
1817RangedU16(u16)
1818RangedU64(u64)
1819RangedU128(u128)
1820RangedUsize(usize)
1821RangedI8(i8)
1822RangedI16(i16)
1823RangedI32(i32)
1824RangedI64(i64)
1825RangedI128(i128)
1826RangedIsize(isize)
1827 ]
1828 }
1829RangedU64 {
1830 mod_name: ranged_u64
1831 alias: ru641832 internal: u64
1833 signed: false
1834unsigned: u64
1835 optional: OptionRangedU641836 optional_alias: Option_ru641837 from: [
1838RangedU8(u8)
1839RangedU16(u16)
1840RangedU32(u32)
1841RangedU128(u128)
1842RangedUsize(usize)
1843RangedI8(i8)
1844RangedI16(i16)
1845RangedI32(i32)
1846RangedI64(i64)
1847RangedI128(i128)
1848RangedIsize(isize)
1849 ]
1850 }
1851RangedU128 {
1852 mod_name: ranged_u128
1853 alias: ru1281854 internal: u128
1855 signed: false
1856unsigned: u128
1857 optional: OptionRangedU1281858 optional_alias: Option_ru1281859 from: [
1860RangedU8(u8)
1861RangedU16(u16)
1862RangedU32(u32)
1863RangedU64(u64)
1864RangedUsize(usize)
1865RangedI8(i8)
1866RangedI16(i16)
1867RangedI32(i32)
1868RangedI64(i64)
1869RangedI128(i128)
1870RangedIsize(isize)
1871 ]
1872 }
1873RangedUsize {
1874 mod_name: ranged_usize
1875 alias: rusize1876 internal: usize
1877 signed: false
1878unsigned: usize
1879 optional: OptionRangedUsize1880 optional_alias: Option_rusize1881 from: [
1882RangedU8(u8)
1883RangedU16(u16)
1884RangedU32(u32)
1885RangedU64(u64)
1886RangedU128(u128)
1887RangedI8(i8)
1888RangedI16(i16)
1889RangedI32(i32)
1890RangedI64(i64)
1891RangedI128(i128)
1892RangedIsize(isize)
1893 ]
1894 manual: [rand_09 rand_010]
1895 }
1896RangedI8 {
1897 mod_name: ranged_i8
1898 alias: ri81899 internal: i8
1900 signed: true
1901unsigned: u8
1902 optional: OptionRangedI81903 optional_alias: Option_ri81904 from: [
1905RangedU8(u8)
1906RangedU16(u16)
1907RangedU32(u32)
1908RangedU64(u64)
1909RangedU128(u128)
1910RangedUsize(usize)
1911RangedI16(i16)
1912RangedI32(i32)
1913RangedI64(i64)
1914RangedI128(i128)
1915RangedIsize(isize)
1916 ]
1917 }
1918RangedI16 {
1919 mod_name: ranged_i16
1920 alias: ri161921 internal: i16
1922 signed: true
1923unsigned: u16
1924 optional: OptionRangedI161925 optional_alias: Option_ri161926 from: [
1927RangedU8(u8)
1928RangedU16(u16)
1929RangedU32(u32)
1930RangedU64(u64)
1931RangedU128(u128)
1932RangedUsize(usize)
1933RangedI8(i8)
1934RangedI32(i32)
1935RangedI64(i64)
1936RangedI128(i128)
1937RangedIsize(isize)
1938 ]
1939 }
1940RangedI32 {
1941 mod_name: ranged_i32
1942 alias: ri321943 internal: i32
1944 signed: true
1945unsigned: u32
1946 optional: OptionRangedI321947 optional_alias: Option_ri321948 from: [
1949RangedU8(u8)
1950RangedU16(u16)
1951RangedU32(u32)
1952RangedU64(u64)
1953RangedU128(u128)
1954RangedUsize(usize)
1955RangedI8(i8)
1956RangedI16(i16)
1957RangedI64(i64)
1958RangedI128(i128)
1959RangedIsize(isize)
1960 ]
1961 }
1962RangedI64 {
1963 mod_name: ranged_i64
1964 alias: ri641965 internal: i64
1966 signed: true
1967unsigned: u64
1968 optional: OptionRangedI641969 optional_alias: Option_ri641970 from: [
1971RangedU8(u8)
1972RangedU16(u16)
1973RangedU32(u32)
1974RangedU64(u64)
1975RangedU128(u128)
1976RangedUsize(usize)
1977RangedI8(i8)
1978RangedI16(i16)
1979RangedI32(i32)
1980RangedI128(i128)
1981RangedIsize(isize)
1982 ]
1983 }
1984RangedI128 {
1985 mod_name: ranged_i128
1986 alias: ri1281987 internal: i128
1988 signed: true
1989unsigned: u128
1990 optional: OptionRangedI1281991 optional_alias: Option_ri1281992 from: [
1993RangedU8(u8)
1994RangedU16(u16)
1995RangedU32(u32)
1996RangedU64(u64)
1997RangedU128(u128)
1998RangedUsize(usize)
1999RangedI8(i8)
2000RangedI16(i16)
2001RangedI32(i32)
2002RangedI64(i64)
2003RangedIsize(isize)
2004 ]
2005 }
2006RangedIsize {
2007 mod_name: ranged_isize
2008 alias: risize2009 internal: isize
2010 signed: true
2011unsigned: usize
2012 optional: OptionRangedIsize2013 optional_alias: Option_risize2014 from: [
2015RangedU8(u8)
2016RangedU16(u16)
2017RangedU32(u32)
2018RangedU64(u64)
2019RangedU128(u128)
2020RangedUsize(usize)
2021RangedI8(i8)
2022RangedI16(i16)
2023RangedI32(i32)
2024RangedI64(i64)
2025RangedI128(i128)
2026 ]
2027 manual: [rand_09 rand_010]
2028 }
2029}20302031#[cfg(feature = "rand09")]
2032impl<const MIN: usize, const MAX: usize> rand09::distr::Distribution<RangedUsize<MIN, MAX>>
2033for rand09::distr::StandardUniform
2034{
2035#[inline]
2036fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
2037const {
2038assert!(MIN <= MAX);
2039 }
20402041#[cfg(target_pointer_width = "16")]
2042let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
2043#[cfg(target_pointer_width = "32")]
2044let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
2045#[cfg(target_pointer_width = "64")]
2046let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
2047#[cfg(not(any(
2048 target_pointer_width = "16",
2049 target_pointer_width = "32",
2050 target_pointer_width = "64"
2051)))]
2052compile_error("platform has unusual (and unsupported) pointer width");
20532054 RangedUsize::new(value).expect("rand failed to generate a valid value")
2055 }
2056}
20572058#[cfg(feature = "rand09")]
2059impl<const MIN: isize, const MAX: isize> rand09::distr::Distribution<RangedIsize<MIN, MAX>>
2060for rand09::distr::StandardUniform
2061{
2062#[inline]
2063fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
2064const {
2065assert!(MIN <= MAX);
2066 }
20672068#[cfg(target_pointer_width = "16")]
2069let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
2070#[cfg(target_pointer_width = "32")]
2071let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
2072#[cfg(target_pointer_width = "64")]
2073let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
2074#[cfg(not(any(
2075 target_pointer_width = "16",
2076 target_pointer_width = "32",
2077 target_pointer_width = "64"
2078)))]
2079compile_error("platform has unusual (and unsupported) pointer width");
20802081 RangedIsize::new(value).expect("rand failed to generate a valid value")
2082 }
2083}
20842085#[cfg(feature = "rand010")]
2086impl<const MIN: usize, const MAX: usize> rand010::distr::Distribution<RangedUsize<MIN, MAX>>
2087for rand010::distr::StandardUniform
2088{
2089#[inline]
2090fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
2091const {
2092assert!(MIN <= MAX);
2093 }
20942095use rand010::RngExt as _;
20962097#[cfg(target_pointer_width = "16")]
2098let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
2099#[cfg(target_pointer_width = "32")]
2100let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
2101#[cfg(target_pointer_width = "64")]
2102let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
2103#[cfg(not(any(
2104 target_pointer_width = "16",
2105 target_pointer_width = "32",
2106 target_pointer_width = "64"
2107)))]
2108compile_error("platform has unusual (and unsupported) pointer width");
21092110 RangedUsize::new(value).expect("rand failed to generate a valid value")
2111 }
2112}
21132114#[cfg(feature = "rand010")]
2115impl<const MIN: isize, const MAX: isize> rand010::distr::Distribution<RangedIsize<MIN, MAX>>
2116for rand010::distr::StandardUniform
2117{
2118#[inline]
2119fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
2120const {
2121assert!(MIN <= MAX);
2122 }
21232124use rand010::RngExt as _;
21252126#[cfg(target_pointer_width = "16")]
2127let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
2128#[cfg(target_pointer_width = "32")]
2129let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
2130#[cfg(target_pointer_width = "64")]
2131let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
2132#[cfg(not(any(
2133 target_pointer_width = "16",
2134 target_pointer_width = "32",
2135 target_pointer_width = "64"
2136)))]
2137compile_error("platform has unusual (and unsupported) pointer width");
21382139 RangedIsize::new(value).expect("rand failed to generate a valid value")
2140 }
2141}