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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TryFromIntError { }
#[automatically_derived]
impl ::core::clone::Clone for TryFromIntError {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TryFromIntError { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TryFromIntError { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TryFromIntError {
#[inline]
fn eq(&self, other: &Self) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TryFromIntError { }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) -> Self {
ParseIntError { kind: ::core::clone::Clone::clone(&self.kind) }
}
}Clone, #[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::marker::StructuralPartialEq for ParseIntError { }
#[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::cmp::PartialEq for ParseIntError {
#[inline]
fn eq(&self, other: &Self) -> 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_fields_are_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>(
231 Unsafe<$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 subtraction. Computes `self - rhs`, returning `None` if the
532 /// resulting 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 multiplication. Computes `self * rhs`, returning `None` if the
558 /// resulting 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 division. 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 /// `rhs` 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 /// `rhs` must not be zero and the result of `self.div_euclid(rhs)` must be in the range
626 /// `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 safety invariants are
667 /// upheld.
668 ///
669 /// # Safety
670 ///
671 /// `rhs` must not be zero, the division must not overflow, and the result must be in
672 /// range.
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, `rhs` is not zero,
679 // and the remainder operation does not overflow.
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 safety
695 /// invariants are upheld.
696 ///
697 /// # Safety
698 ///
699 /// `rhs` must not be zero, the division must not overflow, and the result must be in
700 /// range.
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, `rhs` is not zero,
707 // and the remainder operation does not overflow.
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 /// `rhs` must be less than the number of bits in the inner integer type, and the
773 /// result of `self << rhs` must be in the range `MIN..=MAX`.
774#[must_use = "this returns the result of the operation, without modifying the original"]
775 #[track_caller]
776 #[inline(always)]
777pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
778const { assert!(MIN <= MAX); }
779// Safety: The caller must ensure that the shift count is valid and the result is
780 // in range.
781unsafe {
782// TOD(MSRV 1.93) use `unchecked_shl`
783Self::new_unchecked(self.get().checked_shl(rhs).unwrap_unchecked())
784 }
785 }
786787/// Checked shift right. Computes `self >> rhs`, returning `None` if
788 /// the resulting value is out of range.
789#[must_use = "this returns the result of the operation, without modifying the original"]
790 #[inline]
791pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
792const { assert!(MIN <= MAX); }
793Self::new(const_try_opt!(self.get().checked_shr(rhs)))
794 }
795796/// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
797 ///
798 /// # Safety
799 ///
800 /// `rhs` must be less than the number of bits in the inner integer type, and the
801 /// result of `self >> rhs` must be in the range `MIN..=MAX`.
802#[must_use = "this returns the result of the operation, without modifying the original"]
803 #[track_caller]
804 #[inline(always)]
805pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
806const { assert!(MIN <= MAX); }
807// Safety: The caller must ensure that the shift count is valid and the result is
808 // in range.
809unsafe {
810// TODO(MSRV 1.93) use `unchecked_shr`
811Self::new_unchecked(self.get().checked_shr(rhs).unwrap_unchecked())
812 }
813 }
814815if_signed!($is_signed
816/// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
817 /// value is out of range.
818#[must_use = "this returns the result of the operation, without modifying the original"]
819 #[inline]
820pub const fn checked_abs(self) -> Option<Self> {
821const { assert!(MIN <= MAX); }
822Self::new(const_try_opt!(self.get().checked_abs()))
823 }
824825/// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
826 /// range.
827 ///
828 /// # Safety
829 ///
830 /// The result of `self.abs()` must be in the range `MIN..=MAX`.
831#[must_use = "this returns the result of the operation, without modifying the original"]
832 #[track_caller]
833 #[inline(always)]
834pub const unsafe fn unchecked_abs(self) -> Self {
835const { assert!(MIN <= MAX); }
836// Safety: The caller must ensure that the result is in range.
837unsafe { Self::new_unchecked(self.get().checked_abs().unwrap_unchecked()) }
838 }
839840/// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
841 /// guaranteed to be in range.
842#[must_use = "this returns the result of the operation, without modifying the original"]
843 #[inline(always)]
844pub const fn abs(self) -> Self {
845const {
846assert!(MIN <= MAX);
847assert!(MIN != $internal::MIN);
848assert!(-MIN <= MAX);
849 }
850// <Self as $crate::traits::AbsIsSafe>::ASSERT;
851 // Safety: The compiler asserts that the result is in range.
852unsafe { self.unchecked_abs() }
853 });
854855/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
856 /// value is out of range.
857#[must_use = "this returns the result of the operation, without modifying the original"]
858 #[inline]
859pub const fn checked_pow(self, exp: u32) -> Option<Self> {
860const { assert!(MIN <= MAX); }
861Self::new(const_try_opt!(self.get().checked_pow(exp)))
862 }
863864/// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
865 /// range.
866 ///
867 /// # Safety
868 ///
869 /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
870#[must_use = "this returns the result of the operation, without modifying the original"]
871 #[track_caller]
872 #[inline(always)]
873pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
874const { assert!(MIN <= MAX); }
875// Safety: The caller must ensure that the result is in range.
876unsafe {
877Self::new_unchecked(self.get().checked_pow(exp).unwrap_unchecked())
878 }
879 }
880881/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
882 /// bounds.
883#[must_use = "this returns the result of the operation, without modifying the original"]
884 #[inline]
885pub const fn saturating_add(self, rhs: $internal) -> Self {
886const { assert!(MIN <= MAX); }
887Self::new_saturating(self.get().saturating_add(rhs))
888 }
889890/// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
891 /// bounds.
892#[must_use = "this returns the result of the operation, without modifying the original"]
893 #[inline]
894pub const fn saturating_sub(self, rhs: $internal) -> Self {
895const { assert!(MIN <= MAX); }
896Self::new_saturating(self.get().saturating_sub(rhs))
897 }
898899if_signed!($is_signed
900/// Saturating integer negation. Computes `-self`, saturating at the numeric
901 /// bounds.
902#[must_use = "this returns the result of the operation, without modifying the original"]
903 #[inline]
904pub const fn saturating_neg(self) -> Self {
905const { assert!(MIN <= MAX); }
906Self::new_saturating(self.get().saturating_neg())
907 });
908909if_signed!($is_signed
910/// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
911#[must_use = "this returns the result of the operation, without modifying the original"]
912 #[inline]
913pub const fn saturating_abs(self) -> Self {
914const { assert!(MIN <= MAX); }
915Self::new_saturating(self.get().saturating_abs())
916 });
917918/// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
919 /// bounds.
920#[must_use = "this returns the result of the operation, without modifying the original"]
921 #[inline]
922pub const fn saturating_mul(self, rhs: $internal) -> Self {
923const { assert!(MIN <= MAX); }
924Self::new_saturating(self.get().saturating_mul(rhs))
925 }
926927/// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
928 /// numeric bounds.
929#[must_use = "this returns the result of the operation, without modifying the original"]
930 #[inline]
931pub const fn saturating_pow(self, exp: u32) -> Self {
932const { assert!(MIN <= MAX); }
933Self::new_saturating(self.get().saturating_pow(exp))
934 }
935936if_signed! { $is_signed
937/// Returns `true` if the number is positive and `false` if the number is zero or
938 /// negative.
939#[inline]
940pub const fn is_positive(self) -> bool {
941const { assert!(MIN <= MAX); }
942self.get().is_positive()
943 }
944945/// Returns `true` if the number is negative and `false` if the number is zero or
946 /// positive.
947#[inline]
948pub const fn is_negative(self) -> bool {
949const { assert!(MIN <= MAX); }
950self.get().is_negative()
951 }
952 }
953954/// Compute the `rem_euclid` of this type with its unsigned type equivalent
955// Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
956 // Also because this isn't implemented for normal types in std.
957#[must_use = "this returns the result of the operation, without modifying the original"]
958 #[track_caller]
959 #[inline]
960 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
961const fn rem_euclid_unsigned(
962 rhs: $internal,
963 range_len: $unsigned_type
964) -> $unsigned_type {
965#[allow(unused_comparisons)]
966if rhs >= 0 {
967 (rhs as $unsigned_type) % range_len
968 } else {
969// Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
970 // Can't write -ux or ux::abs() method. This gets around compilation error.
971 // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
972let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
973// Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
974 // Also = 0 in mod range_len arithmetic.
975 // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
976 // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
977 // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
978 // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
979((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
980 }
981 }
982983/// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
984 /// bounds.
985#[must_use = "this returns the result of the operation, without modifying the original"]
986 #[inline]
987 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
988pub const fn wrapping_add(self, rhs: $internal) -> Self {
989const { assert!(MIN <= MAX); }
990// Forward to internal type's impl if same as type.
991if MIN == $internal::MIN && MAX == $internal::MAX {
992// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
993return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
994 }
995996let inner = self.get();
997998// Won't overflow because of std impl forwarding.
999let range_len = MAX.abs_diff(MIN) + 1;
10001001// Calculate the offset with proper handling for negative rhs
1002let offset = Self::rem_euclid_unsigned(rhs, range_len);
10031004let greater_vals = MAX.abs_diff(inner);
1005// No wrap
1006if offset <= greater_vals {
1007// Safety:
1008 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1009 // if inner < 0: Same as >=0 with caveat:
1010 // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
1011 // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
1012 // (the difference doesn't matter since it won't overflow),
1013 // but unsigned integers don't have either method so it won't compile that way.
1014unsafe { Self::new_unchecked(
1015 ((inner as $unsigned_type).wrapping_add(offset)) as $internal
1016) }
1017 }
1018// Wrap
1019else {
1020// Safety:
1021 // - offset < range_len by rem_euclid (MIN + ... safe)
1022 // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
1023 //
1024 // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
1025unsafe { Self::new_unchecked(
1026 ((MIN as $unsigned_type).wrapping_add(
1027 offset - (greater_vals + 1)
1028 )) as $internal
1029) }
1030 }
1031 }
10321033/// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
1034 /// bounds.
1035#[must_use = "this returns the result of the operation, without modifying the original"]
1036 #[inline]
1037 #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
1038pub const fn wrapping_sub(self, rhs: $internal) -> Self {
1039const { assert!(MIN <= MAX); }
1040// Forward to internal type's impl if same as type.
1041if MIN == $internal::MIN && MAX == $internal::MAX {
1042// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1043return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
1044 }
10451046let inner = self.get();
10471048// Won't overflow because of std impl forwarding.
1049let range_len = MAX.abs_diff(MIN) + 1;
10501051// Calculate the offset with proper handling for negative rhs
1052let offset = Self::rem_euclid_unsigned(rhs, range_len);
10531054let lesser_vals = MIN.abs_diff(inner);
1055// No wrap
1056if offset <= lesser_vals {
1057// Safety:
1058 // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
1059 // if inner < 0: Same as >=0 with caveat:
1060 // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
1061 // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
1062 // (the difference doesn't matter since it won't overflow below 0),
1063 // but unsigned integers don't have either method so it won't compile that way.
1064unsafe { Self::new_unchecked(
1065 ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
1066) }
1067 }
1068// Wrap
1069else {
1070// Safety:
1071 // - offset < range_len by rem_euclid (MAX - ... safe)
1072 // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
1073 //
1074 // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
1075unsafe { Self::new_unchecked(
1076 ((MAX as $unsigned_type).wrapping_sub(
1077 offset - (lesser_vals + 1)
1078 )) as $internal
1079) }
1080 }
1081 }
10821083/// Calculates self + rhs.
1084 ///
1085 /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
1086 /// If an overflow would have occurred then the wrapped value is returned.
1087#[must_use = "this returns the result of the operation, without modifying the original"]
1088 #[inline]
1089pub const fn overflowing_add(self, rhs: $internal) -> (Self, bool) {
1090const { assert!(MIN <= MAX); }
10911092// Forward to internal type's impl if same as type.
1093if MIN == $internal::MIN && MAX == $internal::MAX {
1094let (res, overflow) = self.get().overflowing_add(rhs);
10951096// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1097return (unsafe { Self::new_unchecked(res) }, overflow)
1098 }
10991100if let Some(res) = self.checked_add(rhs) {
1101 (res, false)
1102 } else {
1103 (self.wrapping_add(rhs), true)
1104 }
1105 }
11061107/// Calculates self - rhs.
1108 ///
1109 /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
1110 /// If an overflow would have occurred then the wrapped value is returned.
1111#[must_use = "this returns the result of the operation, without modifying the original"]
1112 #[inline]
1113pub const fn overflowing_sub(self, rhs: $internal) -> (Self, bool) {
1114const { assert!(MIN <= MAX); }
11151116// Forward to internal type's impl if same as type.
1117if MIN == $internal::MIN && MAX == $internal::MAX {
1118let (res, overflow) = self.get().overflowing_sub(rhs);
11191120// Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
1121return (unsafe { Self::new_unchecked(res) }, overflow)
1122 }
11231124if let Some(res) = self.checked_sub(rhs) {
1125 (res, false)
1126 } else {
1127 (self.wrapping_sub(rhs), true)
1128 }
1129 }
1130 }
11311132impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
1133/// The value used as the niche. Must not be in the range `MIN..=MAX`.
1134const NICHE: $internal = match (MIN, MAX) {
1135 ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
1136 ($internal::MIN, _) => $internal::MAX,
1137 (_, _) => $internal::MIN,
1138 };
11391140/// An optional ranged value that is not present.
1141#[allow(non_upper_case_globals)]
1142pub const None: Self = Self(Self::NICHE);
11431144/// Creates an optional ranged value that is present.
1145#[allow(non_snake_case)]
1146 #[inline(always)]
1147pub const fn Some(value: $type<MIN, MAX>) -> Self {
1148const { assert!(MIN <= MAX); }
1149Self(value.get())
1150 }
11511152/// Returns the value as the standard library's [`Option`] type.
1153#[inline(always)]
1154pub const fn get(self) -> Option<$type<MIN, MAX>> {
1155const { assert!(MIN <= MAX); }
1156if self.0 == Self::NICHE {
1157None
1158} else {
1159// Safety: A stored value that is not the niche is always in range.
1160Some(unsafe { $type::new_unchecked(self.0) })
1161 }
1162 }
11631164/// Creates an optional ranged integer without checking the value.
1165 ///
1166 /// # Safety
1167 ///
1168 /// The value must be within the range `MIN..=MAX`. As the value used for niche
1169 /// value optimization is unspecified, the provided value must not be the niche
1170 /// value.
1171#[inline(always)]
1172 #[track_caller]
1173pub const unsafe fn some_unchecked(value: $internal) -> Self {
1174const { assert!(MIN <= MAX); }
1175// Safety: The caller must ensure that the value is in range.
1176unsafe { assert_unchecked(MIN <= value && value <= MAX) };
1177Self(value)
1178 }
11791180/// Obtain the inner value of the struct. This is useful for comparisons.
1181#[inline(always)]
1182pub(crate) const fn inner(self) -> $internal {
1183const { assert!(MIN <= MAX); }
1184self.0
1185}
11861187/// Obtain the value of the struct as an `Option` of the primitive type.
1188 ///
1189 /// A call to this function will output a hint to the compiler that the value is in
1190 /// range. In general this will help the optimizer to generate better code, but in edge
1191 /// cases this may lead to worse code generation. To avoid outputting the hint, you can
1192#[doc = concat!(
1193"use [`", stringify!($optional_type), "::get_primitive_without_hint`]."
1194)]
1195 #[inline(always)]
1196pub const fn get_primitive(self) -> Option<$internal> {
1197const { assert!(MIN <= MAX); }
1198Some(const_try_opt!(self.get()).get())
1199 }
12001201/// Obtain the value of the struct as an `Option` of the primitive type.
1202 ///
1203#[doc = concat!(
1204"The returned value is identical to [`", stringify!($optional_type), "::",
1205"get_primitive`]."
1206)]
1207/// Unlike `get_primitive`, no hints are output to the compiler indicating the range
1208 /// that the value is in. Depending on the scenario, this may with be helpful or harmful
1209 /// to optimization.
1210#[inline(always)]
1211pub const fn get_primitive_without_hint(self) -> Option<$internal> {
1212const { assert!(MIN <= MAX); }
1213Some(const_try_opt!(self.get()).get_without_hint())
1214 }
12151216/// Returns `true` if the value is the niche value.
1217#[inline(always)]
1218pub const fn is_none(&self) -> bool {
1219const { assert!(MIN <= MAX); }
1220self.get().is_none()
1221 }
12221223/// Returns `true` if the value is not the niche value.
1224#[inline(always)]
1225pub const fn is_some(&self) -> bool {
1226const { assert!(MIN <= MAX); }
1227self.get().is_some()
1228 }
1229 }
12301231impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
1232#[inline(always)]
1233fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1234const { assert!(MIN <= MAX); }
1235self.get().fmt(f)
1236 }
1237 }
12381239impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
1240#[inline(always)]
1241fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1242const { assert!(MIN <= MAX); }
1243self.get().fmt(f)
1244 }
1245 }
12461247impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
1248#[inline(always)]
1249fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1250const { assert!(MIN <= MAX); }
1251self.get().fmt(f)
1252 }
1253 }
12541255#[cfg(feature = "powerfmt")]
1256impl<
1257const MIN: $internal,
1258const MAX: $internal,
1259 > smart_display::SmartDisplay for $type<MIN, MAX> {
1260type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
12611262#[inline(always)]
1263fn metadata(
1264&self,
1265 f: smart_display::FormatterOptions,
1266 ) -> smart_display::Metadata<'_, Self> {
1267const { assert!(MIN <= MAX); }
1268self.get_ref().metadata(f).reuse()
1269 }
12701271#[inline(always)]
1272fn fmt_with_metadata(
1273&self,
1274 f: &mut fmt::Formatter<'_>,
1275 metadata: smart_display::Metadata<'_, Self>,
1276 ) -> fmt::Result {
1277const { assert!(MIN <= MAX); }
1278self.get().fmt_with_metadata(f, metadata.reuse())
1279 }
1280 }
12811282impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
1283#[inline(always)]
1284fn default() -> Self {
1285const { assert!(MIN <= MAX); }
1286Self::None
1287 }
1288 }
12891290impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
1291#[inline(always)]
1292fn as_ref(&self) -> &$internal {
1293const { assert!(MIN <= MAX); }
1294&self.get_ref()
1295 }
1296 }
12971298impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
1299#[inline(always)]
1300fn borrow(&self) -> &$internal {
1301const { assert!(MIN <= MAX); }
1302&self.get_ref()
1303 }
1304 }
13051306impl<
1307const MIN_A: $internal,
1308const MAX_A: $internal,
1309const MIN_B: $internal,
1310const MAX_B: $internal,
1311 > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1312#[inline(always)]
1313fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
1314const {
1315assert!(MIN_A <= MAX_A);
1316assert!(MIN_B <= MAX_B);
1317 }
1318self.get() == other.get()
1319 }
1320 }
13211322impl<
1323const MIN_A: $internal,
1324const MAX_A: $internal,
1325const MIN_B: $internal,
1326const MAX_B: $internal,
1327 > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1328#[inline(always)]
1329fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
1330const {
1331assert!(MIN_A <= MAX_A);
1332assert!(MIN_B <= MAX_B);
1333 }
1334self.get().map(|value| value.get()) == other.get().map(|value| value.get())
1335 }
1336 }
13371338impl<
1339const MIN_A: $internal,
1340const MAX_A: $internal,
1341const MIN_B: $internal,
1342const MAX_B: $internal,
1343 > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
1344#[inline(always)]
1345fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
1346const {
1347assert!(MIN_A <= MAX_A);
1348assert!(MIN_B <= MAX_B);
1349 }
1350self.get().partial_cmp(&other.get())
1351 }
1352 }
13531354impl<
1355const MIN_A: $internal,
1356const MAX_A: $internal,
1357const MIN_B: $internal,
1358const MAX_B: $internal,
1359 > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
1360#[inline]
1361fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
1362const {
1363assert!(MIN_A <= MAX_A);
1364assert!(MIN_B <= MAX_B);
1365 }
1366if self.is_none() && other.is_none() {
1367Some(Ordering::Equal)
1368 } else if self.is_none() {
1369Some(Ordering::Less)
1370 } else if other.is_none() {
1371Some(Ordering::Greater)
1372 } else {
1373self.inner().partial_cmp(&other.inner())
1374 }
1375 }
1376 }
13771378impl<
1379const MIN: $internal,
1380const MAX: $internal,
1381 > Ord for $optional_type<MIN, MAX> {
1382#[inline]
1383fn cmp(&self, other: &Self) -> Ordering {
1384const { assert!(MIN <= MAX); }
1385if self.is_none() && other.is_none() {
1386 Ordering::Equal
1387 } else if self.is_none() {
1388 Ordering::Less
1389 } else if other.is_none() {
1390 Ordering::Greater
1391 } else {
1392self.inner().cmp(&other.inner())
1393 }
1394 }
1395 }
13961397impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
1398#[inline(always)]
1399fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1400const { assert!(MIN <= MAX); }
1401self.get().fmt(f)
1402 }
1403 }
14041405impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
1406#[inline(always)]
1407fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1408const { assert!(MIN <= MAX); }
1409self.get().fmt(f)
1410 }
1411 }
14121413impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
1414#[inline(always)]
1415fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1416const { assert!(MIN <= MAX); }
1417self.get().fmt(f)
1418 }
1419 }
14201421impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
1422#[inline(always)]
1423fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1424const { assert!(MIN <= MAX); }
1425self.get().fmt(f)
1426 }
1427 }
14281429impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
1430#[inline(always)]
1431fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1432const { assert!(MIN <= MAX); }
1433self.get().fmt(f)
1434 }
1435 }
14361437impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
1438#[inline(always)]
1439fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1440const { assert!(MIN <= MAX); }
1441self.get().fmt(f)
1442 }
1443 }
14441445if_unsigned! { $is_signed
1446impl From<NonZero<$internal>> for $type<1, { $internal::MAX }> {
1447#[inline(always)]
1448fn from(value: NonZero<$internal>) -> Self {
1449Self::from_nonzero(value)
1450 }
1451 }
14521453impl From<$type<1, { $internal::MAX }>> for NonZero<$internal> {
1454#[inline(always)]
1455fn from(value: $type<1, { $internal::MAX }>) -> Self {
1456 value.to_nonzero()
1457 }
1458 }
1459 }
14601461impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
1462#[inline(always)]
1463fn from(value: $type<MIN, MAX>) -> Self {
1464const { assert!(MIN <= MAX); }
1465 value.get()
1466 }
1467 }
14681469impl<
1470const MIN: $internal,
1471const MAX: $internal,
1472 > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
1473#[inline(always)]
1474fn from(value: $type<MIN, MAX>) -> Self {
1475const { assert!(MIN <= MAX); }
1476Self::Some(value)
1477 }
1478 }
14791480impl<
1481const MIN: $internal,
1482const MAX: $internal,
1483 > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
1484#[inline(always)]
1485fn from(value: Option<$type<MIN, MAX>>) -> Self {
1486const { assert!(MIN <= MAX); }
1487match value {
1488Some(value) => Self::Some(value),
1489None => Self::None,
1490 }
1491 }
1492 }
14931494impl<
1495const MIN: $internal,
1496const MAX: $internal,
1497 > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
1498#[inline(always)]
1499fn from(value: $optional_type<MIN, MAX>) -> Self {
1500const { assert!(MIN <= MAX); }
1501 value.get()
1502 }
1503 }
15041505impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
1506type Error = TryFromIntError;
15071508#[inline]
1509fn try_from(value: $internal) -> Result<Self, Self::Error> {
1510const { assert!(MIN <= MAX); }
1511Self::new(value).ok_or(TryFromIntError)
1512 }
1513 }
15141515impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
1516type Err = ParseIntError;
15171518#[inline]
1519fn from_str(s: &str) -> Result<Self, Self::Err> {
1520const { assert!(MIN <= MAX); }
1521let value = s.parse::<$internal>().map_err(|e| ParseIntError {
1522 kind: e.kind().clone()
1523 })?;
1524if value < MIN {
1525Err(ParseIntError { kind: IntErrorKind::NegOverflow })
1526 } else if value > MAX {
1527Err(ParseIntError { kind: IntErrorKind::PosOverflow })
1528 } else {
1529// Safety: The value was previously checked for validity.
1530Ok(unsafe { Self::new_unchecked(value) })
1531 }
1532 }
1533 }
15341535 $(impl<
1536const MIN_SRC: $from_internal,
1537const MAX_SRC: $from_internal,
1538const MIN_DST: $internal,
1539const MAX_DST: $internal,
1540 > From<$from<MIN_SRC, MAX_SRC>> for $type<MIN_DST, MAX_DST>
1541 {
1542#[inline(always)]
1543 #[allow(trivial_numeric_casts, unused_comparisons)]
1544fn from(value: $from<MIN_SRC, MAX_SRC>) -> Self {
1545const {
1546assert!(MIN_SRC <= MAX_SRC, "source range is invalid");
1547assert!(MIN_DST <= MAX_DST, "target range is invalid");
15481549match ($from_internal::MIN == 0, $internal::MIN == 0) {
1550// unsigned -> unsigned
1551(true, true) => {
1552assert!(
1553 MIN_SRC as u128 >= MIN_DST as u128,
1554"minimum value cannot be represented in the target range"
1555);
1556assert!(
1557 MAX_SRC as u128 <= MAX_DST as u128,
1558"maximum value cannot be represented in the target range"
1559);
1560 }
1561// signed -> signed
1562(false, false) => {
1563assert!(
1564 MIN_SRC as i128 >= MIN_DST as i128,
1565"minimum value cannot be represented in the target range"
1566);
1567assert!(
1568 MAX_SRC as i128 <= MAX_DST as i128,
1569"maximum value cannot be represented in the target range"
1570);
1571 }
1572// unsigned -> signed
1573(true, false) => {
1574assert!(
1575 MIN_DST < 0 || MIN_SRC as u128 >= MIN_DST as u128,
1576"minimum value cannot be represented in the target range"
1577);
1578assert!(
1579 MAX_DST >= 0
1580&& MAX_SRC as u128 <= i128::MAX as u128
1581 && MAX_SRC as i128 <= MAX_DST as i128,
1582"maximum value cannot be represented in the target range"
1583);
1584 }
1585// signed -> unsigned
1586(false, true) => {
1587assert!(
1588 MIN_SRC >= 0 && MIN_SRC as u128 >= MIN_DST as u128,
1589"minimum value cannot be represented in the target range"
1590);
1591assert!(
1592 MAX_SRC >= 0 && MAX_SRC as u128 <= MAX_DST as u128,
1593"maximum value cannot be represented in the target range"
1594);
1595 }
1596 }
1597 }
15981599// Safety: The source range is a subset of the destination range.
1600unsafe { $type::new_unchecked(value.get() as $internal) }
1601 }
1602 })+
16031604#[cfg(feature = "serde")]
1605impl<const MIN: $internal, const MAX: $internal> serde_core::Serialize for $type<MIN, MAX> {
1606#[inline(always)]
1607fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1608 {
1609const { assert!(MIN <= MAX); }
1610self.get().serialize(serializer)
1611 }
1612 }
16131614#[cfg(feature = "serde")]
1615impl<
1616const MIN: $internal,
1617const MAX: $internal,
1618 > serde_core::Serialize for $optional_type<MIN, MAX> {
1619#[inline(always)]
1620fn serialize<S: serde_core::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
1621 {
1622const { assert!(MIN <= MAX); }
1623self.get().serialize(serializer)
1624 }
1625 }
16261627#[cfg(feature = "serde")]
1628impl<
1629'de,
1630const MIN: $internal,
1631const MAX: $internal,
1632 > serde_core::Deserialize<'de> for $type<MIN, MAX> {
1633#[inline]
1634fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1635 -> Result<Self, D::Error>
1636 {
1637const { assert!(MIN <= MAX); }
1638let internal = <$internal>::deserialize(deserializer)?;
1639Self::new(internal).ok_or_else(|| {
1640#[cfg(feature = "alloc")]
1641let s = alloc::format!("an integer in the range {}..={}", MIN, MAX);
1642#[cfg(not(feature = "alloc"))]
1643let s = "an integer in the valid range";
16441645 <D::Error as serde_core::de::Error>::invalid_value(
1646 serde_core::de::Unexpected::Other("integer"),
1647&s.as_ref(),
1648 )
1649 })
1650 }
1651 }
16521653#[cfg(feature = "serde")]
1654impl<
1655'de,
1656const MIN: $internal,
1657const MAX: $internal,
1658 > serde_core::Deserialize<'de> for $optional_type<MIN, MAX> {
1659#[inline]
1660fn deserialize<D: serde_core::Deserializer<'de>>(deserializer: D)
1661 -> Result<Self, D::Error>
1662 {
1663const { assert!(MIN <= MAX); }
1664match Option::<$type<MIN, MAX>>::deserialize(deserializer)? {
1665Some(value) => Ok(Self::Some(value)),
1666None => Ok(Self::None),
1667 }
1668 }
1669 }
16701671#[cfg(feature = "rand08")]
1672impl<
1673const MIN: $internal,
1674const MAX: $internal,
1675 > rand08::distributions::Distribution<$type<MIN, MAX>> for rand08::distributions::Standard {
1676#[inline]
1677fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1678const { assert!(MIN <= MAX); }
1679$type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1680 }
1681 }
16821683if_not_manual_rand_09! {
1684 [$($($skips)+)?]
1685#[cfg(feature = "rand09")]
1686impl<
1687const MIN: $internal,
1688const MAX: $internal,
1689 > rand09::distr::Distribution<$type<MIN, MAX>> for rand09::distr::StandardUniform {
1690#[inline]
1691fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1692const { assert!(MIN <= MAX); }
1693$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1694 }
1695 }
1696 }
16971698if_not_manual_rand_010! {
1699 [$($($skips)+)?]
1700#[cfg(feature = "rand010")]
1701impl<
1702const MIN: $internal,
1703const MAX: $internal,
1704 > rand010::distr::Distribution<$type<MIN, MAX>> for rand010::distr::StandardUniform {
1705#[inline]
1706fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
1707const { assert!(MIN <= MAX); }
1708use rand010::RngExt as _;
1709$type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
1710 }
1711 }
1712 }
17131714#[cfg(feature = "rand08")]
1715impl<
1716const MIN: $internal,
1717const MAX: $internal,
1718 > rand08::distributions::Distribution<$optional_type<MIN, MAX>>
1719for rand08::distributions::Standard {
1720#[inline]
1721fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1722const { assert!(MIN <= MAX); }
1723 rng.r#gen::<Option<$type<MIN, MAX>>>().into()
1724 }
1725 }
17261727#[cfg(feature = "rand09")]
1728impl<
1729const MIN: $internal,
1730const MAX: $internal,
1731 > rand09::distr::Distribution<$optional_type<MIN, MAX>>
1732for rand09::distr::StandardUniform {
1733#[inline]
1734fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1735const { assert!(MIN <= MAX); }
1736if rng.random() {
1737$optional_type::None
1738} else {
1739$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1740 }
1741 }
1742 }
17431744#[cfg(feature = "rand010")]
1745impl<
1746const MIN: $internal,
1747const MAX: $internal,
1748 > rand010::distr::Distribution<$optional_type<MIN, MAX>>
1749for rand010::distr::StandardUniform {
1750#[inline]
1751fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
1752const { assert!(MIN <= MAX); }
1753use rand010::RngExt as _;
1754if rng.random() {
1755$optional_type::None
1756} else {
1757$optional_type::Some(rng.random::<$type<MIN, MAX>>())
1758 }
1759 }
1760 }
17611762#[cfg(feature = "num")]
1763impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
1764#[inline(always)]
1765fn min_value() -> Self {
1766const { assert!(MIN <= MAX); }
1767Self::MIN
1768 }
17691770#[inline(always)]
1771fn max_value() -> Self {
1772const { assert!(MIN <= MAX); }
1773Self::MAX
1774 }
1775 }
17761777#[cfg(feature = "quickcheck")]
1778impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
1779#[allow(trivial_numeric_casts)] // Normalize signed and unsigned values to unsigned bits.
1780#[inline]
1781fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1782const { assert!(MIN <= MAX); }
1783if const { MIN == <$internal>::MIN && MAX == <$internal>::MAX } {
1784// Safety: Every value of the inner type is in the full range.
1785unsafe { Self::new_unchecked(<$internal>::arbitrary(g)) }
1786 } else {
1787let range = (MAX as $unsigned_type)
1788 .wrapping_sub(MIN as $unsigned_type)
1789 .wrapping_add(1);
1790let offset = (<$internal>::arbitrary(g) as $unsigned_type)
1791 .wrapping_sub(MIN as $unsigned_type)
1792 % range;
1793let value = (MIN as $unsigned_type).wrapping_add(offset) as $internal;
17941795// Safety: The offset is less than the range width, so the value is in range.
1796unsafe {
1797Self::new_unchecked(value)
1798 }
1799 }
1800 }
18011802#[inline]
1803fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1804 ::alloc::boxed::Box::new(
1805self.get()
1806 .shrink()
1807 .filter_map(Self::new)
1808 )
1809 }
1810 }
18111812#[cfg(feature = "quickcheck")]
1813impl<
1814const MIN: $internal,
1815const MAX: $internal,
1816 > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
1817#[inline]
1818fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1819const { assert!(MIN <= MAX); }
1820Option::<$type<MIN, MAX>>::arbitrary(g).into()
1821 }
18221823#[inline]
1824fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
1825 ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
1826 }
1827 }
1828 )*};
1829}
18301831#[doc = "Equivalent to `RangedU8`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ru8<const MIN : u8, const MAX : u8> = RangedU8<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedU8`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ru8<const MIN : u8, const MAX : u8> =
OptionRangedU8<MIN, MAX>;
#[doc = "A `u8` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedU8<const MIN : u8, const MAX : u8>(Unsafe<u8>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u8, const MAX : u8> ::core::clone::TrivialClone for
RangedU8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::clone::Clone for
RangedU8<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<u8>>;
*self
}
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::marker::Copy for
RangedU8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::cmp::Eq for RangedU8<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<u8>>;
}
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::cmp::Ord for RangedU8<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::hash::Hash for RangedU8<MIN, MAX>
{
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedU8`; similar to `Option<RangedU8>` with better optimization."]
///
#[doc =
"If `MIN` is [`u8::MIN`] _and_ `MAX` is [`u8::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 [`OptionRangedU8::get`]."]
#[repr(transparent)]
pub struct OptionRangedU8<const MIN : u8, const MAX : u8>(u8);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u8, const MAX : u8> ::core::clone::TrivialClone for
OptionRangedU8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::clone::Clone for
OptionRangedU8<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u8>;
*self
}
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::marker::Copy for
OptionRangedU8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::cmp::Eq for
OptionRangedU8<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u8>;
}
}
#[automatically_derived]
impl<const MIN : u8, const MAX : u8> ::core::hash::Hash for
OptionRangedU8<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedU8<0, 0> {
#[doc = "A RangedU8 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : u8>() -> RangedU8<VALUE, VALUE> {
unsafe { RangedU8::new_unchecked(VALUE) }
}
}
impl RangedU8<1, { u8::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<u8>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<u8> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : u8, const MAX : u8> RangedU8<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: u8) -> 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 [`RangedU8::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> u8 {
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 [`RangedU8::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) -> u8 {
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) -> &u8 {
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: u8) -> 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 : u8>() -> 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: u8) -> 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 : u8, const NEW_MAX : u8>(self)
-> RangedU8<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 { RangedU8::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 : u8, const NEW_MAX : u8>(self)
-> Option<RangedU8<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")
};
}
RangedU8::<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 : u8, const NEW_MAX :
u8>(self) -> RangedU8<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 { RangedU8::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::RangedU8;"]
#[doc =
"assert_eq!(RangedU8::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedU8::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 u8::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: u8) -> 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: u8) -> 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: u8) -> 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: u8) -> 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
///
/// `rhs` 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: u8) -> 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: u8) -> 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
///
/// `rhs` 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
u8>(self, rhs: RangedU8<RHS_VALUE, RHS_VALUE>)
-> RangedU8<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedU8::new_unchecked(self.get() % rhs.get()) }
}
/// 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: u8) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u8) -> 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: u8) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u8) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: u8) -> 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: u8) -> 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))
}
/// 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: u8, range_len: u8) -> u8 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u8) % range_len
} else {
let rhs_abs = (u8::wrapping_sub(0, rhs)) as u8;
(((u8::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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u8::MIN && MAX == u8::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 u8).wrapping_add(offset)) as
u8)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u8).wrapping_add(offset - (greater_vals + 1))) as u8)
}
}
}
/// 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: u8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u8::MIN && MAX == u8::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 u8).wrapping_sub(offset)) as
u8)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u8).wrapping_sub(offset - (lesser_vals + 1))) as u8)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: u8) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u8::MIN && MAX == u8::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: u8) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u8::MIN && MAX == u8::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : u8, const MAX : u8> OptionRangedU8<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: u8 =
match (MIN, MAX) {
(u8::MIN, u8::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(u8::MIN, _) => u8::MAX,
(_, _) => u8::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: RangedU8<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<RangedU8<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedU8::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: u8) -> 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) -> u8 {
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 [`OptionRangedU8::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<u8> {
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 [`OptionRangedU8::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<u8> {
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 : u8, const MAX : u8> fmt::Debug for RangedU8<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 : u8, const MAX : u8> fmt::Debug for OptionRangedU8<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 : u8, const MAX : u8> fmt::Display for RangedU8<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 : u8, const MAX : u8> Default for OptionRangedU8<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : u8, const MAX : u8> AsRef<u8> for RangedU8<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &u8 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : u8, const MAX : u8> Borrow<u8> for RangedU8<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &u8 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : u8, const MAX_A : u8, const MIN_B : u8, const MAX_B : u8>
PartialEq<RangedU8<MIN_B, MAX_B>> for RangedU8<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedU8<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 : u8, const MAX_A : u8, const MIN_B : u8, const MAX_B : u8>
PartialEq<OptionRangedU8<MIN_B, MAX_B>> for OptionRangedU8<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedU8<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : u8, const MAX_A : u8, const MIN_B : u8, const MAX_B : u8>
PartialOrd<RangedU8<MIN_B, MAX_B>> for RangedU8<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedU8<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 : u8, const MAX_A : u8, const MIN_B : u8, const MAX_B : u8>
PartialOrd<OptionRangedU8<MIN_B, MAX_B>> for OptionRangedU8<MIN_A, MAX_A>
{
#[inline]
fn partial_cmp(&self, other: &OptionRangedU8<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 : u8, const MAX : u8> Ord for OptionRangedU8<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 : u8, const MAX : u8> fmt::Binary for RangedU8<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 : u8, const MAX : u8> fmt::LowerHex for RangedU8<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 : u8, const MAX : u8> fmt::UpperHex for RangedU8<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 : u8, const MAX : u8> fmt::LowerExp for RangedU8<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 : u8, const MAX : u8> fmt::UpperExp for RangedU8<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 : u8, const MAX : u8> fmt::Octal for RangedU8<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 From<NonZero<u8>> for RangedU8<1, { u8::MAX }> {
#[inline(always)]
fn from(value: NonZero<u8>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedU8<1, { u8::MAX }>> for NonZero<u8> {
#[inline(always)]
fn from(value: RangedU8<1, { u8::MAX }>) -> Self { value.to_nonzero() }
}
impl<const MIN : u8, const MAX : u8> From<RangedU8<MIN, MAX>> for u8 {
#[inline(always)]
fn from(value: RangedU8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u8, const MAX : u8> From<RangedU8<MIN, MAX>> for
OptionRangedU8<MIN, MAX> {
#[inline(always)]
fn from(value: RangedU8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : u8, const MAX : u8> From<Option<RangedU8<MIN, MAX>>> for
OptionRangedU8<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedU8<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 : u8, const MAX : u8> From<OptionRangedU8<MIN, MAX>> for
Option<RangedU8<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedU8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u8, const MAX : u8> TryFrom<u8> for RangedU8<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : u8, const MAX : u8> FromStr for RangedU8<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::<u8>().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 : u16, const MAX_SRC : u16, const MIN_DST : u8, const
MAX_DST : u8> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : u8, const
MAX_DST : u8> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : u8, const
MAX_DST : u8> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : u8, const
MAX_DST : u8> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : u8, const
MAX_DST : u8> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : u8, const MAX_DST
: u8> From<RangedI8<MIN_SRC, MAX_SRC>> for RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : u8, const
MAX_DST : u8> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : u8, const
MAX_DST : u8> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : u8, const
MAX_DST : u8> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : u8, const
MAX_DST : u8> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedU8<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, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : u8, const
MAX_DST : u8> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedU8<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, u8::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 { RangedU8::new_unchecked(value.get() as u8) }
}
}
#[doc = "Equivalent to `RangedU16`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ru16<const MIN : u16, const MAX : u16> = RangedU16<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedU16`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ru16<const MIN : u16, const MAX : u16> =
OptionRangedU16<MIN, MAX>;
#[doc = "A `u16` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedU16<const MIN : u16, const MAX : u16>(Unsafe<u16>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u16, const MAX : u16> ::core::clone::TrivialClone for
RangedU16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::clone::Clone for
RangedU16<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<u16>>;
*self
}
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::marker::Copy for
RangedU16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::cmp::Eq for RangedU16<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<u16>>;
}
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::cmp::Ord for
RangedU16<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::hash::Hash for
RangedU16<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedU16`; similar to `Option<RangedU16>` with better optimization."]
///
#[doc =
"If `MIN` is [`u16::MIN`] _and_ `MAX` is [`u16::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 [`OptionRangedU16::get`]."]
#[repr(transparent)]
pub struct OptionRangedU16<const MIN : u16, const MAX : u16>(u16);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u16, const MAX : u16> ::core::clone::TrivialClone for
OptionRangedU16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::clone::Clone for
OptionRangedU16<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::marker::Copy for
OptionRangedU16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::cmp::Eq for
OptionRangedU16<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u16>;
}
}
#[automatically_derived]
impl<const MIN : u16, const MAX : u16> ::core::hash::Hash for
OptionRangedU16<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedU16<0, 0> {
#[doc = "A RangedU16 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : u16>() -> RangedU16<VALUE, VALUE> {
unsafe { RangedU16::new_unchecked(VALUE) }
}
}
impl RangedU16<1, { u16::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<u16>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<u16> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : u16, const MAX : u16> RangedU16<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: u16) -> 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 [`RangedU16::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> u16 {
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 [`RangedU16::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) -> u16 {
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) -> &u16 {
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: u16) -> 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 : u16>() -> 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: u16) -> 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 : u16, const NEW_MAX : u16>(self)
-> RangedU16<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 { RangedU16::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 : u16, const NEW_MAX : u16>(self)
-> Option<RangedU16<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")
};
}
RangedU16::<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 : u16, const NEW_MAX :
u16>(self) -> RangedU16<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 { RangedU16::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::RangedU16;"]
#[doc =
"assert_eq!(RangedU16::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedU16::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 u16::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: u16) -> 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: u16) -> 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: u16) -> 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: u16) -> 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
///
/// `rhs` 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: u16) -> 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: u16) -> 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
///
/// `rhs` 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
u16>(self, rhs: RangedU16<RHS_VALUE, RHS_VALUE>)
-> RangedU16<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedU16::new_unchecked(self.get() % rhs.get()) }
}
/// 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: u16) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u16) -> 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: u16) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u16) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: u16) -> 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: u16) -> 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))
}
/// 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: u16, range_len: u16) -> u16 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u16) % range_len
} else {
let rhs_abs = (u16::wrapping_sub(0, rhs)) as u16;
(((u16::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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u16::MIN && MAX == u16::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 u16).wrapping_add(offset)) as
u16)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u16).wrapping_add(offset - (greater_vals + 1))) as u16)
}
}
}
/// 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: u16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u16::MIN && MAX == u16::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 u16).wrapping_sub(offset)) as
u16)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u16).wrapping_sub(offset - (lesser_vals + 1))) as u16)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: u16) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u16::MIN && MAX == u16::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: u16) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u16::MIN && MAX == u16::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : u16, const MAX : u16> OptionRangedU16<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: u16 =
match (MIN, MAX) {
(u16::MIN, u16::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(u16::MIN, _) => u16::MAX,
(_, _) => u16::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: RangedU16<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<RangedU16<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedU16::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: u16) -> 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) -> u16 {
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 [`OptionRangedU16::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<u16> {
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 [`OptionRangedU16::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<u16> {
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 : u16, const MAX : u16> fmt::Debug for RangedU16<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 : u16, const MAX : u16> fmt::Debug for
OptionRangedU16<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 : u16, const MAX : u16> fmt::Display for RangedU16<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 : u16, const MAX : u16> Default for OptionRangedU16<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : u16, const MAX : u16> AsRef<u16> for RangedU16<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &u16 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : u16, const MAX : u16> Borrow<u16> for RangedU16<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &u16 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : u16, const MAX_A : u16, const MIN_B : u16, const MAX_B :
u16> PartialEq<RangedU16<MIN_B, MAX_B>> for RangedU16<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedU16<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 : u16, const MAX_A : u16, const MIN_B : u16, const MAX_B :
u16> PartialEq<OptionRangedU16<MIN_B, MAX_B>> for
OptionRangedU16<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedU16<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : u16, const MAX_A : u16, const MIN_B : u16, const MAX_B :
u16> PartialOrd<RangedU16<MIN_B, MAX_B>> for RangedU16<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedU16<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 : u16, const MAX_A : u16, const MIN_B : u16, const MAX_B :
u16> PartialOrd<OptionRangedU16<MIN_B, MAX_B>> for
OptionRangedU16<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedU16<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 : u16, const MAX : u16> Ord for OptionRangedU16<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 : u16, const MAX : u16> fmt::Binary for RangedU16<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 : u16, const MAX : u16> fmt::LowerHex for RangedU16<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 : u16, const MAX : u16> fmt::UpperHex for RangedU16<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 : u16, const MAX : u16> fmt::LowerExp for RangedU16<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 : u16, const MAX : u16> fmt::UpperExp for RangedU16<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 : u16, const MAX : u16> fmt::Octal for RangedU16<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 From<NonZero<u16>> for RangedU16<1, { u16::MAX }> {
#[inline(always)]
fn from(value: NonZero<u16>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedU16<1, { u16::MAX }>> for NonZero<u16> {
#[inline(always)]
fn from(value: RangedU16<1, { u16::MAX }>) -> Self { value.to_nonzero() }
}
impl<const MIN : u16, const MAX : u16> From<RangedU16<MIN, MAX>> for u16 {
#[inline(always)]
fn from(value: RangedU16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u16, const MAX : u16> From<RangedU16<MIN, MAX>> for
OptionRangedU16<MIN, MAX> {
#[inline(always)]
fn from(value: RangedU16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : u16, const MAX : u16> From<Option<RangedU16<MIN, MAX>>> for
OptionRangedU16<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedU16<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 : u16, const MAX : u16> From<OptionRangedU16<MIN, MAX>> for
Option<RangedU16<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedU16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u16, const MAX : u16> TryFrom<u16> for RangedU16<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: u16) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : u16, const MAX : u16> FromStr for RangedU16<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::<u16>().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 : u16, const
MAX_DST : u16> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : u16, const
MAX_DST : u16> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : u16, const
MAX_DST : u16> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : u16, const
MAX_DST : u16> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : u16, const
MAX_DST : u16> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : u16, const
MAX_DST : u16> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : u16, const
MAX_DST : u16> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : u16, const
MAX_DST : u16> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : u16, const
MAX_DST : u16> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : u16, const
MAX_DST : u16> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedU16<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, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : u16, const
MAX_DST : u16> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedU16<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, u16::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 { RangedU16::new_unchecked(value.get() as u16) }
}
}
#[doc = "Equivalent to `RangedU32`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ru32<const MIN : u32, const MAX : u32> = RangedU32<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedU32`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ru32<const MIN : u32, const MAX : u32> =
OptionRangedU32<MIN, MAX>;
#[doc = "A `u32` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedU32<const MIN : u32, const MAX : u32>(Unsafe<u32>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u32, const MAX : u32> ::core::clone::TrivialClone for
RangedU32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::clone::Clone for
RangedU32<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<u32>>;
*self
}
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::marker::Copy for
RangedU32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::cmp::Eq for RangedU32<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<u32>>;
}
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::cmp::Ord for
RangedU32<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::hash::Hash for
RangedU32<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedU32`; similar to `Option<RangedU32>` with better optimization."]
///
#[doc =
"If `MIN` is [`u32::MIN`] _and_ `MAX` is [`u32::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 [`OptionRangedU32::get`]."]
#[repr(transparent)]
pub struct OptionRangedU32<const MIN : u32, const MAX : u32>(u32);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u32, const MAX : u32> ::core::clone::TrivialClone for
OptionRangedU32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::clone::Clone for
OptionRangedU32<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::marker::Copy for
OptionRangedU32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::cmp::Eq for
OptionRangedU32<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}
#[automatically_derived]
impl<const MIN : u32, const MAX : u32> ::core::hash::Hash for
OptionRangedU32<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedU32<0, 0> {
#[doc = "A RangedU32 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : u32>() -> RangedU32<VALUE, VALUE> {
unsafe { RangedU32::new_unchecked(VALUE) }
}
}
impl RangedU32<1, { u32::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<u32>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<u32> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : u32, const MAX : u32> RangedU32<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: u32) -> 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 [`RangedU32::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> u32 {
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 [`RangedU32::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) -> u32 {
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) -> &u32 {
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: u32) -> 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 : u32>() -> 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: u32) -> 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 : u32, const NEW_MAX : u32>(self)
-> RangedU32<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 { RangedU32::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 : u32, const NEW_MAX : u32>(self)
-> Option<RangedU32<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")
};
}
RangedU32::<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 : u32, const NEW_MAX :
u32>(self) -> RangedU32<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 { RangedU32::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::RangedU32;"]
#[doc =
"assert_eq!(RangedU32::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedU32::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 u32::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: u32) -> 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: u32) -> 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: u32) -> 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: u32) -> 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
///
/// `rhs` 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: u32) -> 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: u32) -> 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
///
/// `rhs` 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
u32>(self, rhs: RangedU32<RHS_VALUE, RHS_VALUE>)
-> RangedU32<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedU32::new_unchecked(self.get() % rhs.get()) }
}
/// 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: u32) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u32) -> 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: u32) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u32) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: u32) -> 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: u32) -> 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))
}
/// 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: u32, range_len: u32) -> u32 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u32) % range_len
} else {
let rhs_abs = (u32::wrapping_sub(0, rhs)) as u32;
(((u32::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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u32::MIN && MAX == u32::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 u32).wrapping_add(offset)) as
u32)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u32).wrapping_add(offset - (greater_vals + 1))) as u32)
}
}
}
/// 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: u32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u32::MIN && MAX == u32::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 u32).wrapping_sub(offset)) as
u32)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u32).wrapping_sub(offset - (lesser_vals + 1))) as u32)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: u32) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u32::MIN && MAX == u32::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: u32) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u32::MIN && MAX == u32::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : u32, const MAX : u32> OptionRangedU32<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: u32 =
match (MIN, MAX) {
(u32::MIN, u32::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(u32::MIN, _) => u32::MAX,
(_, _) => u32::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: RangedU32<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<RangedU32<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedU32::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: u32) -> 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) -> u32 {
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 [`OptionRangedU32::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<u32> {
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 [`OptionRangedU32::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<u32> {
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 : u32, const MAX : u32> fmt::Debug for RangedU32<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 : u32, const MAX : u32> fmt::Debug for
OptionRangedU32<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 : u32, const MAX : u32> fmt::Display for RangedU32<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 : u32, const MAX : u32> Default for OptionRangedU32<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : u32, const MAX : u32> AsRef<u32> for RangedU32<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &u32 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : u32, const MAX : u32> Borrow<u32> for RangedU32<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &u32 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : u32, const MAX_A : u32, const MIN_B : u32, const MAX_B :
u32> PartialEq<RangedU32<MIN_B, MAX_B>> for RangedU32<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedU32<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 : u32, const MAX_A : u32, const MIN_B : u32, const MAX_B :
u32> PartialEq<OptionRangedU32<MIN_B, MAX_B>> for
OptionRangedU32<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedU32<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : u32, const MAX_A : u32, const MIN_B : u32, const MAX_B :
u32> PartialOrd<RangedU32<MIN_B, MAX_B>> for RangedU32<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedU32<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 : u32, const MAX_A : u32, const MIN_B : u32, const MAX_B :
u32> PartialOrd<OptionRangedU32<MIN_B, MAX_B>> for
OptionRangedU32<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedU32<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 : u32, const MAX : u32> Ord for OptionRangedU32<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 : u32, const MAX : u32> fmt::Binary for RangedU32<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 : u32, const MAX : u32> fmt::LowerHex for RangedU32<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 : u32, const MAX : u32> fmt::UpperHex for RangedU32<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 : u32, const MAX : u32> fmt::LowerExp for RangedU32<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 : u32, const MAX : u32> fmt::UpperExp for RangedU32<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 : u32, const MAX : u32> fmt::Octal for RangedU32<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 From<NonZero<u32>> for RangedU32<1, { u32::MAX }> {
#[inline(always)]
fn from(value: NonZero<u32>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedU32<1, { u32::MAX }>> for NonZero<u32> {
#[inline(always)]
fn from(value: RangedU32<1, { u32::MAX }>) -> Self { value.to_nonzero() }
}
impl<const MIN : u32, const MAX : u32> From<RangedU32<MIN, MAX>> for u32 {
#[inline(always)]
fn from(value: RangedU32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u32, const MAX : u32> From<RangedU32<MIN, MAX>> for
OptionRangedU32<MIN, MAX> {
#[inline(always)]
fn from(value: RangedU32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : u32, const MAX : u32> From<Option<RangedU32<MIN, MAX>>> for
OptionRangedU32<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedU32<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 : u32, const MAX : u32> From<OptionRangedU32<MIN, MAX>> for
Option<RangedU32<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedU32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u32, const MAX : u32> TryFrom<u32> for RangedU32<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: u32) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : u32, const MAX : u32> FromStr for RangedU32<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::<u32>().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 : u32, const
MAX_DST : u32> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : u32, const
MAX_DST : u32> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : u32, const
MAX_DST : u32> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : u32, const
MAX_DST : u32> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : u32, const
MAX_DST : u32> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : u32, const
MAX_DST : u32> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : u32, const
MAX_DST : u32> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : u32, const
MAX_DST : u32> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : u32, const
MAX_DST : u32> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : u32, const
MAX_DST : u32> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedU32<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, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : u32, const
MAX_DST : u32> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedU32<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, u32::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 { RangedU32::new_unchecked(value.get() as u32) }
}
}
#[doc = "Equivalent to `RangedU64`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ru64<const MIN : u64, const MAX : u64> = RangedU64<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedU64`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ru64<const MIN : u64, const MAX : u64> =
OptionRangedU64<MIN, MAX>;
#[doc = "A `u64` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedU64<const MIN : u64, const MAX : u64>(Unsafe<u64>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u64, const MAX : u64> ::core::clone::TrivialClone for
RangedU64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::clone::Clone for
RangedU64<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<u64>>;
*self
}
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::marker::Copy for
RangedU64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::cmp::Eq for RangedU64<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<u64>>;
}
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::cmp::Ord for
RangedU64<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::hash::Hash for
RangedU64<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedU64`; similar to `Option<RangedU64>` with better optimization."]
///
#[doc =
"If `MIN` is [`u64::MIN`] _and_ `MAX` is [`u64::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 [`OptionRangedU64::get`]."]
#[repr(transparent)]
pub struct OptionRangedU64<const MIN : u64, const MAX : u64>(u64);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u64, const MAX : u64> ::core::clone::TrivialClone for
OptionRangedU64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::clone::Clone for
OptionRangedU64<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u64>;
*self
}
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::marker::Copy for
OptionRangedU64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::cmp::Eq for
OptionRangedU64<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u64>;
}
}
#[automatically_derived]
impl<const MIN : u64, const MAX : u64> ::core::hash::Hash for
OptionRangedU64<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedU64<0, 0> {
#[doc = "A RangedU64 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : u64>() -> RangedU64<VALUE, VALUE> {
unsafe { RangedU64::new_unchecked(VALUE) }
}
}
impl RangedU64<1, { u64::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<u64>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<u64> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : u64, const MAX : u64> RangedU64<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: u64) -> 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 [`RangedU64::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> u64 {
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 [`RangedU64::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) -> u64 {
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) -> &u64 {
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: u64) -> 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 : u64>() -> 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: u64) -> 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 : u64, const NEW_MAX : u64>(self)
-> RangedU64<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 { RangedU64::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 : u64, const NEW_MAX : u64>(self)
-> Option<RangedU64<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")
};
}
RangedU64::<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 : u64, const NEW_MAX :
u64>(self) -> RangedU64<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 { RangedU64::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::RangedU64;"]
#[doc =
"assert_eq!(RangedU64::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedU64::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 u64::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: u64) -> 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: u64) -> 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: u64) -> 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: u64) -> 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
///
/// `rhs` 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: u64) -> 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: u64) -> 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
///
/// `rhs` 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
u64>(self, rhs: RangedU64<RHS_VALUE, RHS_VALUE>)
-> RangedU64<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedU64::new_unchecked(self.get() % rhs.get()) }
}
/// 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: u64) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u64) -> 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: u64) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u64) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: u64) -> 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: u64) -> 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))
}
/// 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: u64, range_len: u64) -> u64 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u64) % range_len
} else {
let rhs_abs = (u64::wrapping_sub(0, rhs)) as u64;
(((u64::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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u64::MIN && MAX == u64::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 u64).wrapping_add(offset)) as
u64)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u64).wrapping_add(offset - (greater_vals + 1))) as u64)
}
}
}
/// 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: u64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u64::MIN && MAX == u64::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 u64).wrapping_sub(offset)) as
u64)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u64).wrapping_sub(offset - (lesser_vals + 1))) as u64)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: u64) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u64::MIN && MAX == u64::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: u64) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u64::MIN && MAX == u64::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : u64, const MAX : u64> OptionRangedU64<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: u64 =
match (MIN, MAX) {
(u64::MIN, u64::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(u64::MIN, _) => u64::MAX,
(_, _) => u64::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: RangedU64<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<RangedU64<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedU64::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: u64) -> 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) -> u64 {
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 [`OptionRangedU64::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<u64> {
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 [`OptionRangedU64::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<u64> {
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 : u64, const MAX : u64> fmt::Debug for RangedU64<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 : u64, const MAX : u64> fmt::Debug for
OptionRangedU64<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 : u64, const MAX : u64> fmt::Display for RangedU64<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 : u64, const MAX : u64> Default for OptionRangedU64<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : u64, const MAX : u64> AsRef<u64> for RangedU64<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &u64 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : u64, const MAX : u64> Borrow<u64> for RangedU64<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &u64 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : u64, const MAX_A : u64, const MIN_B : u64, const MAX_B :
u64> PartialEq<RangedU64<MIN_B, MAX_B>> for RangedU64<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedU64<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 : u64, const MAX_A : u64, const MIN_B : u64, const MAX_B :
u64> PartialEq<OptionRangedU64<MIN_B, MAX_B>> for
OptionRangedU64<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedU64<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : u64, const MAX_A : u64, const MIN_B : u64, const MAX_B :
u64> PartialOrd<RangedU64<MIN_B, MAX_B>> for RangedU64<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedU64<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 : u64, const MAX_A : u64, const MIN_B : u64, const MAX_B :
u64> PartialOrd<OptionRangedU64<MIN_B, MAX_B>> for
OptionRangedU64<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedU64<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 : u64, const MAX : u64> Ord for OptionRangedU64<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 : u64, const MAX : u64> fmt::Binary for RangedU64<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 : u64, const MAX : u64> fmt::LowerHex for RangedU64<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 : u64, const MAX : u64> fmt::UpperHex for RangedU64<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 : u64, const MAX : u64> fmt::LowerExp for RangedU64<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 : u64, const MAX : u64> fmt::UpperExp for RangedU64<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 : u64, const MAX : u64> fmt::Octal for RangedU64<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 From<NonZero<u64>> for RangedU64<1, { u64::MAX }> {
#[inline(always)]
fn from(value: NonZero<u64>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedU64<1, { u64::MAX }>> for NonZero<u64> {
#[inline(always)]
fn from(value: RangedU64<1, { u64::MAX }>) -> Self { value.to_nonzero() }
}
impl<const MIN : u64, const MAX : u64> From<RangedU64<MIN, MAX>> for u64 {
#[inline(always)]
fn from(value: RangedU64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u64, const MAX : u64> From<RangedU64<MIN, MAX>> for
OptionRangedU64<MIN, MAX> {
#[inline(always)]
fn from(value: RangedU64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : u64, const MAX : u64> From<Option<RangedU64<MIN, MAX>>> for
OptionRangedU64<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedU64<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 : u64, const MAX : u64> From<OptionRangedU64<MIN, MAX>> for
Option<RangedU64<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedU64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u64, const MAX : u64> TryFrom<u64> for RangedU64<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: u64) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : u64, const MAX : u64> FromStr for RangedU64<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::<u64>().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 : u64, const
MAX_DST : u64> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : u64, const
MAX_DST : u64> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : u64, const
MAX_DST : u64> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : u64, const
MAX_DST : u64> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : u64, const
MAX_DST : u64> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : u64, const
MAX_DST : u64> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : u64, const
MAX_DST : u64> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : u64, const
MAX_DST : u64> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : u64, const
MAX_DST : u64> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : u64, const
MAX_DST : u64> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedU64<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, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : u64, const
MAX_DST : u64> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedU64<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, u64::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 { RangedU64::new_unchecked(value.get() as u64) }
}
}
#[doc = "Equivalent to `RangedU128`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ru128<const MIN : u128, const MAX : u128> = RangedU128<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedU128`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ru128<const MIN : u128, const MAX : u128> =
OptionRangedU128<MIN, MAX>;
#[doc = "A `u128` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedU128<const MIN : u128, const MAX : u128>(Unsafe<u128>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u128, const MAX : u128> ::core::clone::TrivialClone
for RangedU128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::clone::Clone for
RangedU128<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<u128>>;
*self
}
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::marker::Copy for
RangedU128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::cmp::Eq for
RangedU128<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<u128>>;
}
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::cmp::Ord for
RangedU128<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::hash::Hash for
RangedU128<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedU128`; similar to `Option<RangedU128>` with better optimization."]
///
#[doc =
"If `MIN` is [`u128::MIN`] _and_ `MAX` is [`u128::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 [`OptionRangedU128::get`]."]
#[repr(transparent)]
pub struct OptionRangedU128<const MIN : u128, const MAX : u128>(u128);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : u128, const MAX : u128> ::core::clone::TrivialClone
for OptionRangedU128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::clone::Clone for
OptionRangedU128<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u128>;
*self
}
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::marker::Copy for
OptionRangedU128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::cmp::Eq for
OptionRangedU128<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u128>;
}
}
#[automatically_derived]
impl<const MIN : u128, const MAX : u128> ::core::hash::Hash for
OptionRangedU128<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedU128<0, 0> {
#[doc = "A RangedU128 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : u128>() -> RangedU128<VALUE, VALUE> {
unsafe { RangedU128::new_unchecked(VALUE) }
}
}
impl RangedU128<1, { u128::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<u128>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<u128> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : u128, const MAX : u128> RangedU128<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: u128) -> 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 [`RangedU128::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> u128 {
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 [`RangedU128::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) -> u128 {
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) -> &u128 {
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: u128) -> 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 : u128>() -> 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: u128) -> 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 : u128, const NEW_MAX : u128>(self)
-> RangedU128<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 { RangedU128::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 : u128, const NEW_MAX : u128>(self)
-> Option<RangedU128<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")
};
}
RangedU128::<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 : u128, const NEW_MAX :
u128>(self) -> RangedU128<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 { RangedU128::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::RangedU128;"]
#[doc =
"assert_eq!(RangedU128::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedU128::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 u128::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: u128) -> 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: u128) -> 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: u128) -> 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: u128) -> 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
///
/// `rhs` 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: u128) -> 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: u128) -> 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
///
/// `rhs` 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
u128>(self, rhs: RangedU128<RHS_VALUE, RHS_VALUE>)
-> RangedU128<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedU128::new_unchecked(self.get() % rhs.get()) }
}
/// 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: u128) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u128) -> 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: u128) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: u128) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: u128) -> 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: u128) -> 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))
}
/// 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: u128, range_len: u128) -> u128 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u128) % range_len
} else {
let rhs_abs = (u128::wrapping_sub(0, rhs)) as u128;
(((u128::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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u128::MIN && MAX == u128::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 u128).wrapping_add(offset)) as
u128)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u128).wrapping_add(offset - (greater_vals + 1))) as u128)
}
}
}
/// 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: u128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u128::MIN && MAX == u128::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 u128).wrapping_sub(offset)) as
u128)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u128).wrapping_sub(offset - (lesser_vals + 1))) as u128)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: u128) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u128::MIN && MAX == u128::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: u128) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == u128::MIN && MAX == u128::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : u128, const MAX : u128> OptionRangedU128<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: u128 =
match (MIN, MAX) {
(u128::MIN, u128::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(u128::MIN, _) => u128::MAX,
(_, _) => u128::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: RangedU128<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<RangedU128<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedU128::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: u128) -> 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) -> u128 {
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 [`OptionRangedU128::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<u128> {
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 [`OptionRangedU128::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<u128> {
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 : u128, const MAX : u128> fmt::Debug for RangedU128<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 : u128, const MAX : u128> fmt::Debug for
OptionRangedU128<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 : u128, const MAX : u128> fmt::Display for RangedU128<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 : u128, const MAX : u128> Default for
OptionRangedU128<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : u128, const MAX : u128> AsRef<u128> for RangedU128<MIN, MAX>
{
#[inline(always)]
fn as_ref(&self) -> &u128 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : u128, const MAX : u128> Borrow<u128> for RangedU128<MIN, MAX>
{
#[inline(always)]
fn borrow(&self) -> &u128 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : u128, const MAX_A : u128, const MIN_B : u128, const MAX_B :
u128> PartialEq<RangedU128<MIN_B, MAX_B>> for RangedU128<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedU128<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 : u128, const MAX_A : u128, const MIN_B : u128, const MAX_B :
u128> PartialEq<OptionRangedU128<MIN_B, MAX_B>> for
OptionRangedU128<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedU128<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : u128, const MAX_A : u128, const MIN_B : u128, const MAX_B :
u128> PartialOrd<RangedU128<MIN_B, MAX_B>> for RangedU128<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedU128<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 : u128, const MAX_A : u128, const MIN_B : u128, const MAX_B :
u128> PartialOrd<OptionRangedU128<MIN_B, MAX_B>> for
OptionRangedU128<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedU128<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 : u128, const MAX : u128> Ord for OptionRangedU128<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 : u128, const MAX : u128> fmt::Binary for RangedU128<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 : u128, const MAX : u128> fmt::LowerHex for
RangedU128<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 : u128, const MAX : u128> fmt::UpperHex for
RangedU128<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 : u128, const MAX : u128> fmt::LowerExp for
RangedU128<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 : u128, const MAX : u128> fmt::UpperExp for
RangedU128<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 : u128, const MAX : u128> fmt::Octal for RangedU128<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 From<NonZero<u128>> for RangedU128<1, { u128::MAX }> {
#[inline(always)]
fn from(value: NonZero<u128>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedU128<1, { u128::MAX }>> for NonZero<u128> {
#[inline(always)]
fn from(value: RangedU128<1, { u128::MAX }>) -> Self {
value.to_nonzero()
}
}
impl<const MIN : u128, const MAX : u128> From<RangedU128<MIN, MAX>> for u128 {
#[inline(always)]
fn from(value: RangedU128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u128, const MAX : u128> From<RangedU128<MIN, MAX>> for
OptionRangedU128<MIN, MAX> {
#[inline(always)]
fn from(value: RangedU128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : u128, const MAX : u128> From<Option<RangedU128<MIN, MAX>>>
for OptionRangedU128<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedU128<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 : u128, const MAX : u128> From<OptionRangedU128<MIN, MAX>> for
Option<RangedU128<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedU128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : u128, const MAX : u128> TryFrom<u128> for
RangedU128<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: u128) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : u128, const MAX : u128> FromStr for RangedU128<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::<u128>().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 : u128, const
MAX_DST : u128> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : u128, const
MAX_DST : u128> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : u128, const
MAX_DST : u128> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : u128, const
MAX_DST : u128> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : u128, const
MAX_DST : u128> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : u128, const
MAX_DST : u128> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : u128, const
MAX_DST : u128> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : u128, const
MAX_DST : u128> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : u128, const
MAX_DST : u128> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : u128, const
MAX_DST : u128> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedU128<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, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : u128, const
MAX_DST : u128> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedU128<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, u128::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 { RangedU128::new_unchecked(value.get() as u128) }
}
}
#[doc = "Equivalent to `RangedUsize`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type rusize<const MIN : usize, const MAX : usize> = RangedUsize<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedUsize`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_rusize<const MIN : usize, const MAX : usize> =
OptionRangedUsize<MIN, MAX>;
#[doc = "A `usize` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedUsize<const MIN : usize, const MAX : usize>(Unsafe<usize>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : usize, const MAX : usize> ::core::clone::TrivialClone
for RangedUsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::clone::Clone for
RangedUsize<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<usize>>;
*self
}
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::marker::Copy for
RangedUsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::cmp::Eq for
RangedUsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<usize>>;
}
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::cmp::Ord for
RangedUsize<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::hash::Hash for
RangedUsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedUsize`; similar to `Option<RangedUsize>` with better optimization."]
///
#[doc =
"If `MIN` is [`usize::MIN`] _and_ `MAX` is [`usize::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 [`OptionRangedUsize::get`]."]
#[repr(transparent)]
pub struct OptionRangedUsize<const MIN : usize, const MAX : usize>(usize);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : usize, const MAX : usize> ::core::clone::TrivialClone
for OptionRangedUsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::clone::Clone for
OptionRangedUsize<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<usize>;
*self
}
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::marker::Copy for
OptionRangedUsize<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::cmp::Eq for
OptionRangedUsize<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<usize>;
}
}
#[automatically_derived]
impl<const MIN : usize, const MAX : usize> ::core::hash::Hash for
OptionRangedUsize<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedUsize<0, 0> {
#[doc = "A RangedUsize that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : usize>() -> RangedUsize<VALUE, VALUE> {
unsafe { RangedUsize::new_unchecked(VALUE) }
}
}
impl RangedUsize<1, { usize::MAX }> {
#[doc = r" Creates a ranged integer from a non-zero value."]
#[inline(always)]
pub const fn from_nonzero(value: NonZero<usize>) -> Self {
unsafe { Self::new_unchecked(value.get()) }
}
#[doc = r" Creates a non-zero value from a ranged integer."]
#[inline(always)]
pub const fn to_nonzero(self) -> NonZero<usize> {
unsafe { NonZero::new_unchecked(self.get()) }
}
}
impl<const MIN : usize, const MAX : usize> RangedUsize<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: usize) -> 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 [`RangedUsize::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> usize {
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 [`RangedUsize::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) -> usize {
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) -> &usize {
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: usize) -> 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 : usize>() -> 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: usize) -> 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 : usize, const NEW_MAX : usize>(self)
-> RangedUsize<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 { RangedUsize::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 : usize, const NEW_MAX : usize>(self)
-> Option<RangedUsize<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")
};
}
RangedUsize::<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 : usize, const NEW_MAX
: usize>(self) -> RangedUsize<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 { RangedUsize::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::RangedUsize;"]
#[doc =
"assert_eq!(RangedUsize::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedUsize::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 usize::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: usize) -> 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: usize) -> 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: usize) -> 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: usize) -> 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
///
/// `rhs` 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: usize) -> 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: usize) -> 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
///
/// `rhs` 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe {
Self::new_unchecked(self.get().checked_div_euclid(rhs).unwrap_unchecked())
}
}
#[doc =
r" Remainder. Computes `self % rhs`, statically guaranteeing that the returned value"]
#[doc = r" is in range."]
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[track_caller]
#[inline]
pub const fn rem<const RHS_VALUE :
usize>(self, rhs: RangedUsize<RHS_VALUE, RHS_VALUE>)
-> RangedUsize<0, RHS_VALUE> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { RangedUsize::new_unchecked(self.get() % rhs.get()) }
}
/// 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: usize) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: usize) -> 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: usize) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: usize) -> 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 !(MAX == 0) {
::core::panicking::panic("assertion failed: MAX == 0")
};
}
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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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())
}
}
/// 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: usize) -> 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new_saturating(self.get().saturating_sub(rhs))
}
/// 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: usize) -> 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))
}
/// 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: usize, range_len: usize) -> usize {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as usize) % range_len
} else {
let rhs_abs = (usize::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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == usize::MIN && MAX == usize::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
usize)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
usize).wrapping_add(offset - (greater_vals + 1))) as usize)
}
}
}
/// 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: usize) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == usize::MIN && MAX == usize::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
usize)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
usize).wrapping_sub(offset - (lesser_vals + 1))) as usize)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: usize) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == usize::MIN && MAX == usize::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: usize) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == usize::MIN && MAX == usize::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : usize, const MAX : usize> OptionRangedUsize<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: usize =
match (MIN, MAX) {
(usize::MIN, usize::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(usize::MIN, _) => usize::MAX,
(_, _) => usize::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: RangedUsize<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<RangedUsize<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedUsize::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: usize) -> 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) -> usize {
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 [`OptionRangedUsize::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<usize> {
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 [`OptionRangedUsize::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<usize> {
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 : usize, const MAX : usize> fmt::Debug for
RangedUsize<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 : usize, const MAX : usize> fmt::Debug for
OptionRangedUsize<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 : usize, const MAX : usize> fmt::Display for
RangedUsize<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 : usize, const MAX : usize> Default for
OptionRangedUsize<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : usize, const MAX : usize> AsRef<usize> for
RangedUsize<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &usize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : usize, const MAX : usize> Borrow<usize> for
RangedUsize<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &usize {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : usize, const MAX_A : usize, const MIN_B : usize, const
MAX_B : usize> PartialEq<RangedUsize<MIN_B, MAX_B>> for
RangedUsize<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedUsize<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 : usize, const MAX_A : usize, const MIN_B : usize, const
MAX_B : usize> PartialEq<OptionRangedUsize<MIN_B, MAX_B>> for
OptionRangedUsize<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedUsize<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : usize, const MAX_A : usize, const MIN_B : usize, const
MAX_B : usize> PartialOrd<RangedUsize<MIN_B, MAX_B>> for
RangedUsize<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedUsize<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 : usize, const MAX_A : usize, const MIN_B : usize, const
MAX_B : usize> PartialOrd<OptionRangedUsize<MIN_B, MAX_B>> for
OptionRangedUsize<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedUsize<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 : usize, const MAX : usize> Ord for OptionRangedUsize<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 : usize, const MAX : usize> fmt::Binary for
RangedUsize<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 : usize, const MAX : usize> fmt::LowerHex for
RangedUsize<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 : usize, const MAX : usize> fmt::UpperHex for
RangedUsize<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 : usize, const MAX : usize> fmt::LowerExp for
RangedUsize<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 : usize, const MAX : usize> fmt::UpperExp for
RangedUsize<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 : usize, const MAX : usize> fmt::Octal for
RangedUsize<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 From<NonZero<usize>> for RangedUsize<1, { usize::MAX }> {
#[inline(always)]
fn from(value: NonZero<usize>) -> Self { Self::from_nonzero(value) }
}
impl From<RangedUsize<1, { usize::MAX }>> for NonZero<usize> {
#[inline(always)]
fn from(value: RangedUsize<1, { usize::MAX }>) -> Self {
value.to_nonzero()
}
}
impl<const MIN : usize, const MAX : usize> From<RangedUsize<MIN, MAX>> for
usize {
#[inline(always)]
fn from(value: RangedUsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : usize, const MAX : usize> From<RangedUsize<MIN, MAX>> for
OptionRangedUsize<MIN, MAX> {
#[inline(always)]
fn from(value: RangedUsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : usize, const MAX : usize> From<Option<RangedUsize<MIN, MAX>>>
for OptionRangedUsize<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedUsize<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 : usize, const MAX : usize> From<OptionRangedUsize<MIN, MAX>>
for Option<RangedUsize<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedUsize<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : usize, const MAX : usize> TryFrom<usize> for
RangedUsize<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: usize) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : usize, const MAX : usize> FromStr for RangedUsize<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::<usize>().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 : usize, const
MAX_DST : usize> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : usize, const
MAX_DST : usize> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : usize, const
MAX_DST : usize> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : usize, const
MAX_DST : usize> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : usize, const
MAX_DST : usize> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : usize, const
MAX_DST : usize> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : usize, const
MAX_DST : usize> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : usize, const
MAX_DST : usize> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : usize, const
MAX_DST : usize> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : usize, const
MAX_DST : usize> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedUsize<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, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : usize,
const MAX_DST : usize> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedUsize<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, usize::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 { RangedUsize::new_unchecked(value.get() as usize) }
}
}
#[doc = "Equivalent to `RangedI8`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ri8<const MIN : i8, const MAX : i8> = RangedI8<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedI8`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ri8<const MIN : i8, const MAX : i8> =
OptionRangedI8<MIN, MAX>;
#[doc = "An `i8` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedI8<const MIN : i8, const MAX : i8>(Unsafe<i8>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i8, const MAX : i8> ::core::clone::TrivialClone for
RangedI8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::clone::Clone for
RangedI8<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<i8>>;
*self
}
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::marker::Copy for
RangedI8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::cmp::Eq for RangedI8<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<i8>>;
}
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::cmp::Ord for RangedI8<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::hash::Hash for RangedI8<MIN, MAX>
{
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedI8`; similar to `Option<RangedI8>` with better optimization."]
///
#[doc =
"If `MIN` is [`i8::MIN`] _and_ `MAX` is [`i8::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 [`OptionRangedI8::get`]."]
#[repr(transparent)]
pub struct OptionRangedI8<const MIN : i8, const MAX : i8>(i8);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i8, const MAX : i8> ::core::clone::TrivialClone for
OptionRangedI8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::clone::Clone for
OptionRangedI8<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i8>;
*self
}
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::marker::Copy for
OptionRangedI8<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::cmp::Eq for
OptionRangedI8<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i8>;
}
}
#[automatically_derived]
impl<const MIN : i8, const MAX : i8> ::core::hash::Hash for
OptionRangedI8<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedI8<0, 0> {
#[doc = "A RangedI8 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : i8>() -> RangedI8<VALUE, VALUE> {
unsafe { RangedI8::new_unchecked(VALUE) }
}
}
impl<const MIN : i8, const MAX : i8> RangedI8<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: i8) -> 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 [`RangedI8::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> i8 {
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 [`RangedI8::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) -> i8 {
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) -> &i8 {
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: i8) -> 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 : i8>() -> 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: i8) -> 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 : i8, const NEW_MAX : i8>(self)
-> RangedI8<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 { RangedI8::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 : i8, const NEW_MAX : i8>(self)
-> Option<RangedI8<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")
};
}
RangedI8::<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 : i8, const NEW_MAX :
i8>(self) -> RangedI8<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 { RangedI8::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::RangedI8;"]
#[doc =
"assert_eq!(RangedI8::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedI8::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 i8::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: i8) -> 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: i8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: i8) -> 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: i8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: i8) -> 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: i8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: i8) -> 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
///
/// `rhs` 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: i8) -> 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: i8) -> 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
///
/// `rhs` 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: i8) -> 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: i8) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i8) -> 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: i8) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i8) -> 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 != i8::MIN) {
::core::panicking::panic("assertion failed: MIN != i8::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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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 != i8::MIN) {
::core::panicking::panic("assertion failed: MIN != i8::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: i8) -> 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: i8) -> 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`, 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: i8) -> 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: i8, range_len: u8) -> u8 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u8) % range_len
} else {
let rhs_abs = (i8::wrapping_sub(0, rhs)) as u8;
(((u8::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: i8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i8::MIN && MAX == i8::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 u8).wrapping_add(offset)) as
i8)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u8).wrapping_add(offset - (greater_vals + 1))) as i8)
}
}
}
/// 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: i8) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i8::MIN && MAX == i8::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 u8).wrapping_sub(offset)) as
i8)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u8).wrapping_sub(offset - (lesser_vals + 1))) as i8)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: i8) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i8::MIN && MAX == i8::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: i8) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i8::MIN && MAX == i8::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : i8, const MAX : i8> OptionRangedI8<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: i8 =
match (MIN, MAX) {
(i8::MIN, i8::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(i8::MIN, _) => i8::MAX,
(_, _) => i8::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: RangedI8<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<RangedI8<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedI8::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: i8) -> 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) -> i8 {
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 [`OptionRangedI8::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<i8> {
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 [`OptionRangedI8::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<i8> {
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 : i8, const MAX : i8> fmt::Debug for RangedI8<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 : i8, const MAX : i8> fmt::Debug for OptionRangedI8<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 : i8, const MAX : i8> fmt::Display for RangedI8<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 : i8, const MAX : i8> Default for OptionRangedI8<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : i8, const MAX : i8> AsRef<i8> for RangedI8<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &i8 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : i8, const MAX : i8> Borrow<i8> for RangedI8<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &i8 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : i8, const MAX_A : i8, const MIN_B : i8, const MAX_B : i8>
PartialEq<RangedI8<MIN_B, MAX_B>> for RangedI8<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedI8<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 : i8, const MAX_A : i8, const MIN_B : i8, const MAX_B : i8>
PartialEq<OptionRangedI8<MIN_B, MAX_B>> for OptionRangedI8<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedI8<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : i8, const MAX_A : i8, const MIN_B : i8, const MAX_B : i8>
PartialOrd<RangedI8<MIN_B, MAX_B>> for RangedI8<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedI8<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 : i8, const MAX_A : i8, const MIN_B : i8, const MAX_B : i8>
PartialOrd<OptionRangedI8<MIN_B, MAX_B>> for OptionRangedI8<MIN_A, MAX_A>
{
#[inline]
fn partial_cmp(&self, other: &OptionRangedI8<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 : i8, const MAX : i8> Ord for OptionRangedI8<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 : i8, const MAX : i8> fmt::Binary for RangedI8<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 : i8, const MAX : i8> fmt::LowerHex for RangedI8<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 : i8, const MAX : i8> fmt::UpperHex for RangedI8<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 : i8, const MAX : i8> fmt::LowerExp for RangedI8<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 : i8, const MAX : i8> fmt::UpperExp for RangedI8<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 : i8, const MAX : i8> fmt::Octal for RangedI8<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 : i8, const MAX : i8> From<RangedI8<MIN, MAX>> for i8 {
#[inline(always)]
fn from(value: RangedI8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i8, const MAX : i8> From<RangedI8<MIN, MAX>> for
OptionRangedI8<MIN, MAX> {
#[inline(always)]
fn from(value: RangedI8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : i8, const MAX : i8> From<Option<RangedI8<MIN, MAX>>> for
OptionRangedI8<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedI8<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 : i8, const MAX : i8> From<OptionRangedI8<MIN, MAX>> for
Option<RangedI8<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedI8<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i8, const MAX : i8> TryFrom<i8> for RangedI8<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: i8) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : i8, const MAX : i8> FromStr for RangedI8<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::<i8>().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 : i8, const MAX_DST
: i8> From<RangedU8<MIN_SRC, MAX_SRC>> for RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : i8, const
MAX_DST : i8> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : i8, const
MAX_DST : i8> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : i8, const
MAX_DST : i8> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : i8, const
MAX_DST : i8> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : i8, const
MAX_DST : i8> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : i8, const
MAX_DST : i8> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : i8, const
MAX_DST : i8> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : i8, const
MAX_DST : i8> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : i8, const
MAX_DST : i8> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedI8<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, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : i8, const
MAX_DST : i8> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedI8<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, i8::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 { RangedI8::new_unchecked(value.get() as i8) }
}
}
#[doc = "Equivalent to `RangedI16`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ri16<const MIN : i16, const MAX : i16> = RangedI16<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedI16`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ri16<const MIN : i16, const MAX : i16> =
OptionRangedI16<MIN, MAX>;
#[doc = "An `i16` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedI16<const MIN : i16, const MAX : i16>(Unsafe<i16>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i16, const MAX : i16> ::core::clone::TrivialClone for
RangedI16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::clone::Clone for
RangedI16<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<i16>>;
*self
}
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::marker::Copy for
RangedI16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::cmp::Eq for RangedI16<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<i16>>;
}
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::cmp::Ord for
RangedI16<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::hash::Hash for
RangedI16<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedI16`; similar to `Option<RangedI16>` with better optimization."]
///
#[doc =
"If `MIN` is [`i16::MIN`] _and_ `MAX` is [`i16::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 [`OptionRangedI16::get`]."]
#[repr(transparent)]
pub struct OptionRangedI16<const MIN : i16, const MAX : i16>(i16);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i16, const MAX : i16> ::core::clone::TrivialClone for
OptionRangedI16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::clone::Clone for
OptionRangedI16<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i16>;
*self
}
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::marker::Copy for
OptionRangedI16<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::cmp::Eq for
OptionRangedI16<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i16>;
}
}
#[automatically_derived]
impl<const MIN : i16, const MAX : i16> ::core::hash::Hash for
OptionRangedI16<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedI16<0, 0> {
#[doc = "A RangedI16 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : i16>() -> RangedI16<VALUE, VALUE> {
unsafe { RangedI16::new_unchecked(VALUE) }
}
}
impl<const MIN : i16, const MAX : i16> RangedI16<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: i16) -> 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 [`RangedI16::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> i16 {
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 [`RangedI16::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) -> i16 {
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) -> &i16 {
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: i16) -> 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 : i16>() -> 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: i16) -> 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 : i16, const NEW_MAX : i16>(self)
-> RangedI16<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 { RangedI16::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 : i16, const NEW_MAX : i16>(self)
-> Option<RangedI16<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")
};
}
RangedI16::<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 : i16, const NEW_MAX :
i16>(self) -> RangedI16<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 { RangedI16::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::RangedI16;"]
#[doc =
"assert_eq!(RangedI16::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedI16::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 i16::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: i16) -> 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: i16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: i16) -> 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: i16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: i16) -> 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: i16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: i16) -> 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
///
/// `rhs` 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: i16) -> 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: i16) -> 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
///
/// `rhs` 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: i16) -> 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: i16) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i16) -> 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: i16) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i16) -> 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 != i16::MIN) {
::core::panicking::panic("assertion failed: MIN != i16::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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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 != i16::MIN) {
::core::panicking::panic("assertion failed: MIN != i16::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: i16) -> 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: i16) -> 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`, 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: i16) -> 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: i16, range_len: u16) -> u16 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u16) % range_len
} else {
let rhs_abs = (i16::wrapping_sub(0, rhs)) as u16;
(((u16::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: i16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i16::MIN && MAX == i16::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 u16).wrapping_add(offset)) as
i16)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u16).wrapping_add(offset - (greater_vals + 1))) as i16)
}
}
}
/// 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: i16) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i16::MIN && MAX == i16::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 u16).wrapping_sub(offset)) as
i16)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u16).wrapping_sub(offset - (lesser_vals + 1))) as i16)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: i16) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i16::MIN && MAX == i16::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: i16) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i16::MIN && MAX == i16::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : i16, const MAX : i16> OptionRangedI16<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: i16 =
match (MIN, MAX) {
(i16::MIN, i16::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(i16::MIN, _) => i16::MAX,
(_, _) => i16::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: RangedI16<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<RangedI16<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedI16::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: i16) -> 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) -> i16 {
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 [`OptionRangedI16::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<i16> {
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 [`OptionRangedI16::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<i16> {
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 : i16, const MAX : i16> fmt::Debug for RangedI16<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 : i16, const MAX : i16> fmt::Debug for
OptionRangedI16<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 : i16, const MAX : i16> fmt::Display for RangedI16<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 : i16, const MAX : i16> Default for OptionRangedI16<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : i16, const MAX : i16> AsRef<i16> for RangedI16<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &i16 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : i16, const MAX : i16> Borrow<i16> for RangedI16<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &i16 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : i16, const MAX_A : i16, const MIN_B : i16, const MAX_B :
i16> PartialEq<RangedI16<MIN_B, MAX_B>> for RangedI16<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedI16<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 : i16, const MAX_A : i16, const MIN_B : i16, const MAX_B :
i16> PartialEq<OptionRangedI16<MIN_B, MAX_B>> for
OptionRangedI16<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedI16<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : i16, const MAX_A : i16, const MIN_B : i16, const MAX_B :
i16> PartialOrd<RangedI16<MIN_B, MAX_B>> for RangedI16<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedI16<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 : i16, const MAX_A : i16, const MIN_B : i16, const MAX_B :
i16> PartialOrd<OptionRangedI16<MIN_B, MAX_B>> for
OptionRangedI16<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedI16<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 : i16, const MAX : i16> Ord for OptionRangedI16<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 : i16, const MAX : i16> fmt::Binary for RangedI16<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 : i16, const MAX : i16> fmt::LowerHex for RangedI16<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 : i16, const MAX : i16> fmt::UpperHex for RangedI16<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 : i16, const MAX : i16> fmt::LowerExp for RangedI16<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 : i16, const MAX : i16> fmt::UpperExp for RangedI16<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 : i16, const MAX : i16> fmt::Octal for RangedI16<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 : i16, const MAX : i16> From<RangedI16<MIN, MAX>> for i16 {
#[inline(always)]
fn from(value: RangedI16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i16, const MAX : i16> From<RangedI16<MIN, MAX>> for
OptionRangedI16<MIN, MAX> {
#[inline(always)]
fn from(value: RangedI16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : i16, const MAX : i16> From<Option<RangedI16<MIN, MAX>>> for
OptionRangedI16<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedI16<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 : i16, const MAX : i16> From<OptionRangedI16<MIN, MAX>> for
Option<RangedI16<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedI16<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i16, const MAX : i16> TryFrom<i16> for RangedI16<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: i16) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : i16, const MAX : i16> FromStr for RangedI16<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::<i16>().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 : i16, const
MAX_DST : i16> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : i16, const
MAX_DST : i16> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : i16, const
MAX_DST : i16> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : i16, const
MAX_DST : i16> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : i16, const
MAX_DST : i16> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : i16, const
MAX_DST : i16> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : i16, const
MAX_DST : i16> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : i16, const
MAX_DST : i16> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : i16, const
MAX_DST : i16> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : i16, const
MAX_DST : i16> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedI16<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, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : i16, const
MAX_DST : i16> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedI16<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, i16::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 { RangedI16::new_unchecked(value.get() as i16) }
}
}
#[doc = "Equivalent to `RangedI32`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ri32<const MIN : i32, const MAX : i32> = RangedI32<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedI32`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ri32<const MIN : i32, const MAX : i32> =
OptionRangedI32<MIN, MAX>;
#[doc = "An `i32` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedI32<const MIN : i32, const MAX : i32>(Unsafe<i32>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i32, const MAX : i32> ::core::clone::TrivialClone for
RangedI32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::clone::Clone for
RangedI32<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<i32>>;
*self
}
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::marker::Copy for
RangedI32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::cmp::Eq for RangedI32<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<i32>>;
}
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::cmp::Ord for
RangedI32<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::hash::Hash for
RangedI32<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedI32`; similar to `Option<RangedI32>` with better optimization."]
///
#[doc =
"If `MIN` is [`i32::MIN`] _and_ `MAX` is [`i32::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 [`OptionRangedI32::get`]."]
#[repr(transparent)]
pub struct OptionRangedI32<const MIN : i32, const MAX : i32>(i32);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i32, const MAX : i32> ::core::clone::TrivialClone for
OptionRangedI32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::clone::Clone for
OptionRangedI32<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i32>;
*self
}
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::marker::Copy for
OptionRangedI32<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::cmp::Eq for
OptionRangedI32<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i32>;
}
}
#[automatically_derived]
impl<const MIN : i32, const MAX : i32> ::core::hash::Hash for
OptionRangedI32<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedI32<0, 0> {
#[doc = "A RangedI32 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : i32>() -> RangedI32<VALUE, VALUE> {
unsafe { RangedI32::new_unchecked(VALUE) }
}
}
impl<const MIN : i32, const MAX : i32> RangedI32<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: i32) -> 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 [`RangedI32::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> i32 {
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 [`RangedI32::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) -> i32 {
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) -> &i32 {
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: i32) -> 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 : i32>() -> 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: i32) -> 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 : i32, const NEW_MAX : i32>(self)
-> RangedI32<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 { RangedI32::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 : i32, const NEW_MAX : i32>(self)
-> Option<RangedI32<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")
};
}
RangedI32::<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 : i32, const NEW_MAX :
i32>(self) -> RangedI32<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 { RangedI32::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::RangedI32;"]
#[doc =
"assert_eq!(RangedI32::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedI32::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 i32::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: i32) -> 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: i32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: i32) -> 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: i32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: i32) -> 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: i32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: i32) -> 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
///
/// `rhs` 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: i32) -> 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: i32) -> 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
///
/// `rhs` 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: i32) -> 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: i32) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i32) -> 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: i32) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i32) -> 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 != i32::MIN) {
::core::panicking::panic("assertion failed: MIN != i32::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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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 != i32::MIN) {
::core::panicking::panic("assertion failed: MIN != i32::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: i32) -> 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: i32) -> 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`, 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: i32) -> 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: i32, range_len: u32) -> u32 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u32) % range_len
} else {
let rhs_abs = (i32::wrapping_sub(0, rhs)) as u32;
(((u32::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: i32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i32::MIN && MAX == i32::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 u32).wrapping_add(offset)) as
i32)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u32).wrapping_add(offset - (greater_vals + 1))) as i32)
}
}
}
/// 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: i32) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i32::MIN && MAX == i32::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 u32).wrapping_sub(offset)) as
i32)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u32).wrapping_sub(offset - (lesser_vals + 1))) as i32)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: i32) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i32::MIN && MAX == i32::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: i32) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i32::MIN && MAX == i32::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : i32, const MAX : i32> OptionRangedI32<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: i32 =
match (MIN, MAX) {
(i32::MIN, i32::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(i32::MIN, _) => i32::MAX,
(_, _) => i32::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: RangedI32<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<RangedI32<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedI32::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: i32) -> 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) -> i32 {
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 [`OptionRangedI32::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<i32> {
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 [`OptionRangedI32::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<i32> {
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 : i32, const MAX : i32> fmt::Debug for RangedI32<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 : i32, const MAX : i32> fmt::Debug for
OptionRangedI32<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 : i32, const MAX : i32> fmt::Display for RangedI32<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 : i32, const MAX : i32> Default for OptionRangedI32<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : i32, const MAX : i32> AsRef<i32> for RangedI32<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &i32 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : i32, const MAX : i32> Borrow<i32> for RangedI32<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &i32 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : i32, const MAX_A : i32, const MIN_B : i32, const MAX_B :
i32> PartialEq<RangedI32<MIN_B, MAX_B>> for RangedI32<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedI32<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 : i32, const MAX_A : i32, const MIN_B : i32, const MAX_B :
i32> PartialEq<OptionRangedI32<MIN_B, MAX_B>> for
OptionRangedI32<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedI32<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : i32, const MAX_A : i32, const MIN_B : i32, const MAX_B :
i32> PartialOrd<RangedI32<MIN_B, MAX_B>> for RangedI32<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedI32<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 : i32, const MAX_A : i32, const MIN_B : i32, const MAX_B :
i32> PartialOrd<OptionRangedI32<MIN_B, MAX_B>> for
OptionRangedI32<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedI32<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 : i32, const MAX : i32> Ord for OptionRangedI32<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 : i32, const MAX : i32> fmt::Binary for RangedI32<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 : i32, const MAX : i32> fmt::LowerHex for RangedI32<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 : i32, const MAX : i32> fmt::UpperHex for RangedI32<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 : i32, const MAX : i32> fmt::LowerExp for RangedI32<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 : i32, const MAX : i32> fmt::UpperExp for RangedI32<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 : i32, const MAX : i32> fmt::Octal for RangedI32<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 : i32, const MAX : i32> From<RangedI32<MIN, MAX>> for i32 {
#[inline(always)]
fn from(value: RangedI32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i32, const MAX : i32> From<RangedI32<MIN, MAX>> for
OptionRangedI32<MIN, MAX> {
#[inline(always)]
fn from(value: RangedI32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : i32, const MAX : i32> From<Option<RangedI32<MIN, MAX>>> for
OptionRangedI32<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedI32<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 : i32, const MAX : i32> From<OptionRangedI32<MIN, MAX>> for
Option<RangedI32<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedI32<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i32, const MAX : i32> TryFrom<i32> for RangedI32<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: i32) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : i32, const MAX : i32> FromStr for RangedI32<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::<i32>().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 : i32, const
MAX_DST : i32> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : i32, const
MAX_DST : i32> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : i32, const
MAX_DST : i32> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : i32, const
MAX_DST : i32> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : i32, const
MAX_DST : i32> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : i32, const
MAX_DST : i32> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : i32, const
MAX_DST : i32> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : i32, const
MAX_DST : i32> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : i32, const
MAX_DST : i32> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : i32, const
MAX_DST : i32> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedI32<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, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : i32, const
MAX_DST : i32> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedI32<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, i32::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 { RangedI32::new_unchecked(value.get() as i32) }
}
}
#[doc = "Equivalent to `RangedI64`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ri64<const MIN : i64, const MAX : i64> = RangedI64<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedI64`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ri64<const MIN : i64, const MAX : i64> =
OptionRangedI64<MIN, MAX>;
#[doc = "An `i64` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedI64<const MIN : i64, const MAX : i64>(Unsafe<i64>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i64, const MAX : i64> ::core::clone::TrivialClone for
RangedI64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::clone::Clone for
RangedI64<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<i64>>;
*self
}
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::marker::Copy for
RangedI64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::cmp::Eq for RangedI64<MIN, MAX>
{
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<i64>>;
}
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::cmp::Ord for
RangedI64<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::hash::Hash for
RangedI64<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedI64`; similar to `Option<RangedI64>` with better optimization."]
///
#[doc =
"If `MIN` is [`i64::MIN`] _and_ `MAX` is [`i64::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 [`OptionRangedI64::get`]."]
#[repr(transparent)]
pub struct OptionRangedI64<const MIN : i64, const MAX : i64>(i64);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i64, const MAX : i64> ::core::clone::TrivialClone for
OptionRangedI64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::clone::Clone for
OptionRangedI64<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i64>;
*self
}
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::marker::Copy for
OptionRangedI64<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::cmp::Eq for
OptionRangedI64<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i64>;
}
}
#[automatically_derived]
impl<const MIN : i64, const MAX : i64> ::core::hash::Hash for
OptionRangedI64<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedI64<0, 0> {
#[doc = "A RangedI64 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : i64>() -> RangedI64<VALUE, VALUE> {
unsafe { RangedI64::new_unchecked(VALUE) }
}
}
impl<const MIN : i64, const MAX : i64> RangedI64<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: i64) -> 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 [`RangedI64::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> i64 {
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 [`RangedI64::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) -> i64 {
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) -> &i64 {
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: i64) -> 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 : i64>() -> 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: i64) -> 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 : i64, const NEW_MAX : i64>(self)
-> RangedI64<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 { RangedI64::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 : i64, const NEW_MAX : i64>(self)
-> Option<RangedI64<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")
};
}
RangedI64::<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 : i64, const NEW_MAX :
i64>(self) -> RangedI64<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 { RangedI64::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::RangedI64;"]
#[doc =
"assert_eq!(RangedI64::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedI64::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 i64::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: i64) -> 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: i64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: i64) -> 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: i64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: i64) -> 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: i64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: i64) -> 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
///
/// `rhs` 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: i64) -> 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: i64) -> 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
///
/// `rhs` 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: i64) -> 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: i64) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i64) -> 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: i64) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i64) -> 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 != i64::MIN) {
::core::panicking::panic("assertion failed: MIN != i64::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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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 != i64::MIN) {
::core::panicking::panic("assertion failed: MIN != i64::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: i64) -> 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: i64) -> 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`, 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: i64) -> 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: i64, range_len: u64) -> u64 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u64) % range_len
} else {
let rhs_abs = (i64::wrapping_sub(0, rhs)) as u64;
(((u64::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: i64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i64::MIN && MAX == i64::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 u64).wrapping_add(offset)) as
i64)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u64).wrapping_add(offset - (greater_vals + 1))) as i64)
}
}
}
/// 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: i64) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i64::MIN && MAX == i64::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 u64).wrapping_sub(offset)) as
i64)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u64).wrapping_sub(offset - (lesser_vals + 1))) as i64)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: i64) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i64::MIN && MAX == i64::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: i64) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i64::MIN && MAX == i64::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : i64, const MAX : i64> OptionRangedI64<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: i64 =
match (MIN, MAX) {
(i64::MIN, i64::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(i64::MIN, _) => i64::MAX,
(_, _) => i64::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: RangedI64<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<RangedI64<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedI64::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: i64) -> 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) -> i64 {
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 [`OptionRangedI64::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<i64> {
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 [`OptionRangedI64::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<i64> {
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 : i64, const MAX : i64> fmt::Debug for RangedI64<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 : i64, const MAX : i64> fmt::Debug for
OptionRangedI64<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 : i64, const MAX : i64> fmt::Display for RangedI64<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 : i64, const MAX : i64> Default for OptionRangedI64<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : i64, const MAX : i64> AsRef<i64> for RangedI64<MIN, MAX> {
#[inline(always)]
fn as_ref(&self) -> &i64 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : i64, const MAX : i64> Borrow<i64> for RangedI64<MIN, MAX> {
#[inline(always)]
fn borrow(&self) -> &i64 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : i64, const MAX_A : i64, const MIN_B : i64, const MAX_B :
i64> PartialEq<RangedI64<MIN_B, MAX_B>> for RangedI64<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedI64<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 : i64, const MAX_A : i64, const MIN_B : i64, const MAX_B :
i64> PartialEq<OptionRangedI64<MIN_B, MAX_B>> for
OptionRangedI64<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedI64<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : i64, const MAX_A : i64, const MIN_B : i64, const MAX_B :
i64> PartialOrd<RangedI64<MIN_B, MAX_B>> for RangedI64<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedI64<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 : i64, const MAX_A : i64, const MIN_B : i64, const MAX_B :
i64> PartialOrd<OptionRangedI64<MIN_B, MAX_B>> for
OptionRangedI64<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedI64<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 : i64, const MAX : i64> Ord for OptionRangedI64<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 : i64, const MAX : i64> fmt::Binary for RangedI64<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 : i64, const MAX : i64> fmt::LowerHex for RangedI64<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 : i64, const MAX : i64> fmt::UpperHex for RangedI64<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 : i64, const MAX : i64> fmt::LowerExp for RangedI64<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 : i64, const MAX : i64> fmt::UpperExp for RangedI64<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 : i64, const MAX : i64> fmt::Octal for RangedI64<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 : i64, const MAX : i64> From<RangedI64<MIN, MAX>> for i64 {
#[inline(always)]
fn from(value: RangedI64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i64, const MAX : i64> From<RangedI64<MIN, MAX>> for
OptionRangedI64<MIN, MAX> {
#[inline(always)]
fn from(value: RangedI64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : i64, const MAX : i64> From<Option<RangedI64<MIN, MAX>>> for
OptionRangedI64<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedI64<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 : i64, const MAX : i64> From<OptionRangedI64<MIN, MAX>> for
Option<RangedI64<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedI64<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i64, const MAX : i64> TryFrom<i64> for RangedI64<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: i64) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : i64, const MAX : i64> FromStr for RangedI64<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::<i64>().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 : i64, const
MAX_DST : i64> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : i64, const
MAX_DST : i64> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : i64, const
MAX_DST : i64> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : i64, const
MAX_DST : i64> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : i64, const
MAX_DST : i64> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : i64, const
MAX_DST : i64> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : i64, const
MAX_DST : i64> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : i64, const
MAX_DST : i64> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : i64, const
MAX_DST : i64> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : i128, const MAX_SRC : i128, const MIN_DST : i64, const
MAX_DST : i64> From<RangedI128<MIN_SRC, MAX_SRC>> for
RangedI64<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, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : i64, const
MAX_DST : i64> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedI64<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, i64::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 { RangedI64::new_unchecked(value.get() as i64) }
}
}
#[doc = "Equivalent to `RangedI128`"]
#[expect(non_camel_case_types, reason = "symmetry with primitives")]
pub type ri128<const MIN : i128, const MAX : i128> = RangedI128<MIN, MAX>;
#[doc = "Equivalent to `OptionRangedI128`"]
#[expect(non_camel_case_types, reason = "closest visually to `Option<T>`")]
pub type Option_ri128<const MIN : i128, const MAX : i128> =
OptionRangedI128<MIN, MAX>;
#[doc = "An `i128` that is known to be in the range `MIN..=MAX`."]
#[repr(transparent)]
pub struct RangedI128<const MIN : i128, const MAX : i128>(Unsafe<i128>);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i128, const MAX : i128> ::core::clone::TrivialClone
for RangedI128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::clone::Clone for
RangedI128<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Unsafe<i128>>;
*self
}
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::marker::Copy for
RangedI128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::cmp::Eq for
RangedI128<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Unsafe<i128>>;
}
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::cmp::Ord for
RangedI128<MIN, MAX> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::hash::Hash for
RangedI128<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
#[doc =
"An optional `RangedI128`; similar to `Option<RangedI128>` with better optimization."]
///
#[doc =
"If `MIN` is [`i128::MIN`] _and_ `MAX` is [`i128::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 [`OptionRangedI128::get`]."]
#[repr(transparent)]
pub struct OptionRangedI128<const MIN : i128, const MAX : i128>(i128);
#[automatically_derived]
#[doc(hidden)]
unsafe impl<const MIN : i128, const MAX : i128> ::core::clone::TrivialClone
for OptionRangedI128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::clone::Clone for
OptionRangedI128<MIN, MAX> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i128>;
*self
}
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::marker::Copy for
OptionRangedI128<MIN, MAX> {
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::cmp::Eq for
OptionRangedI128<MIN, MAX> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i128>;
}
}
#[automatically_derived]
impl<const MIN : i128, const MAX : i128> ::core::hash::Hash for
OptionRangedI128<MIN, MAX> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}
impl RangedI128<0, 0> {
#[doc = "A RangedI128 that is always `VALUE`."]
#[inline(always)]
pub const fn exact<const VALUE : i128>() -> RangedI128<VALUE, VALUE> {
unsafe { RangedI128::new_unchecked(VALUE) }
}
}
impl<const MIN : i128, const MAX : i128> RangedI128<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: i128) -> 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 [`RangedI128::get_without_hint`]."]
#[track_caller]
#[inline(always)]
pub const fn get(self) -> i128 {
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 [`RangedI128::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) -> i128 {
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) -> &i128 {
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: i128) -> 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 : i128>() -> 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: i128) -> 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 : i128, const NEW_MAX : i128>(self)
-> RangedI128<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 { RangedI128::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 : i128, const NEW_MAX : i128>(self)
-> Option<RangedI128<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")
};
}
RangedI128::<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 : i128, const NEW_MAX :
i128>(self) -> RangedI128<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 { RangedI128::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::RangedI128;"]
#[doc =
"assert_eq!(RangedI128::<5, 10>::from_str_radix(\"A\", 16), Ok(RangedI128::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 i128::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: i128) -> 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: i128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_add(rhs)) }
}
/// Checked integer subtraction. 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: i128) -> 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: i128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_sub(rhs)) }
}
/// Checked integer multiplication. 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: i128) -> 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: i128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
unsafe { Self::new_unchecked(self.get().unchecked_mul(rhs)) }
}
/// Checked integer division. 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: i128) -> 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
///
/// `rhs` 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: i128) -> 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: i128) -> 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
///
/// `rhs` 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: i128) -> 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: i128) -> 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i128) -> 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: i128) -> 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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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: i128) -> 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 != i128::MIN) {
::core::panicking::panic("assertion failed: MIN != i128::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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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 != i128::MIN) {
::core::panicking::panic("assertion failed: MIN != i128::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: i128) -> 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: i128) -> 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`, 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: i128) -> 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: i128, range_len: u128) -> u128 {
#[allow(unused_comparisons)]
if rhs >= 0 {
(rhs as u128) % range_len
} else {
let rhs_abs = (i128::wrapping_sub(0, rhs)) as u128;
(((u128::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: i128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i128::MIN && MAX == i128::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 u128).wrapping_add(offset)) as
i128)
}
} else {
unsafe {
Self::new_unchecked(((MIN as
u128).wrapping_add(offset - (greater_vals + 1))) as i128)
}
}
}
/// 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: i128) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i128::MIN && MAX == i128::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 u128).wrapping_sub(offset)) as
i128)
}
} else {
unsafe {
Self::new_unchecked(((MAX as
u128).wrapping_sub(offset - (lesser_vals + 1))) as i128)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: i128) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i128::MIN && MAX == i128::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: i128) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == i128::MIN && MAX == i128::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
impl<const MIN : i128, const MAX : i128> OptionRangedI128<MIN, MAX> {
/// The value used as the niche. Must not be in the range `MIN..=MAX`.
const NICHE: i128 =
match (MIN, MAX) {
(i128::MIN, i128::MAX) => {
::core::panicking::panic_fmt(format_args!("type has no niche"));
}
(i128::MIN, _) => i128::MAX,
(_, _) => i128::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: RangedI128<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<RangedI128<MIN, MAX>> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if self.0 == Self::NICHE {
None
} else { Some(unsafe { RangedI128::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: i128) -> 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) -> i128 {
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 [`OptionRangedI128::get_primitive_without_hint`]."]
#[inline(always)]
pub const fn get_primitive(self) -> Option<i128> {
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 [`OptionRangedI128::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<i128> {
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 : i128, const MAX : i128> fmt::Debug for RangedI128<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 : i128, const MAX : i128> fmt::Debug for
OptionRangedI128<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 : i128, const MAX : i128> fmt::Display for RangedI128<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 : i128, const MAX : i128> Default for
OptionRangedI128<MIN, MAX> {
#[inline(always)]
fn default() -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::None
}
}
impl<const MIN : i128, const MAX : i128> AsRef<i128> for RangedI128<MIN, MAX>
{
#[inline(always)]
fn as_ref(&self) -> &i128 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN : i128, const MAX : i128> Borrow<i128> for RangedI128<MIN, MAX>
{
#[inline(always)]
fn borrow(&self) -> &i128 {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
&self.get_ref()
}
}
impl<const MIN_A : i128, const MAX_A : i128, const MIN_B : i128, const MAX_B :
i128> PartialEq<RangedI128<MIN_B, MAX_B>> for RangedI128<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &RangedI128<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 : i128, const MAX_A : i128, const MIN_B : i128, const MAX_B :
i128> PartialEq<OptionRangedI128<MIN_B, MAX_B>> for
OptionRangedI128<MIN_A, MAX_A> {
#[inline(always)]
fn eq(&self, other: &OptionRangedI128<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().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
impl<const MIN_A : i128, const MAX_A : i128, const MIN_B : i128, const MAX_B :
i128> PartialOrd<RangedI128<MIN_B, MAX_B>> for RangedI128<MIN_A, MAX_A> {
#[inline(always)]
fn partial_cmp(&self, other: &RangedI128<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 : i128, const MAX_A : i128, const MIN_B : i128, const MAX_B :
i128> PartialOrd<OptionRangedI128<MIN_B, MAX_B>> for
OptionRangedI128<MIN_A, MAX_A> {
#[inline]
fn partial_cmp(&self, other: &OptionRangedI128<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 : i128, const MAX : i128> Ord for OptionRangedI128<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 : i128, const MAX : i128> fmt::Binary for RangedI128<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 : i128, const MAX : i128> fmt::LowerHex for
RangedI128<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 : i128, const MAX : i128> fmt::UpperHex for
RangedI128<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 : i128, const MAX : i128> fmt::LowerExp for
RangedI128<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 : i128, const MAX : i128> fmt::UpperExp for
RangedI128<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 : i128, const MAX : i128> fmt::Octal for RangedI128<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 : i128, const MAX : i128> From<RangedI128<MIN, MAX>> for i128 {
#[inline(always)]
fn from(value: RangedI128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i128, const MAX : i128> From<RangedI128<MIN, MAX>> for
OptionRangedI128<MIN, MAX> {
#[inline(always)]
fn from(value: RangedI128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::Some(value)
}
}
impl<const MIN : i128, const MAX : i128> From<Option<RangedI128<MIN, MAX>>>
for OptionRangedI128<MIN, MAX> {
#[inline(always)]
fn from(value: Option<RangedI128<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 : i128, const MAX : i128> From<OptionRangedI128<MIN, MAX>> for
Option<RangedI128<MIN, MAX>> {
#[inline(always)]
fn from(value: OptionRangedI128<MIN, MAX>) -> Self {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
value.get()
}
}
impl<const MIN : i128, const MAX : i128> TryFrom<i128> for
RangedI128<MIN, MAX> {
type Error = TryFromIntError;
#[inline]
fn try_from(value: i128) -> Result<Self, Self::Error> {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
Self::new(value).ok_or(TryFromIntError)
}
}
impl<const MIN : i128, const MAX : i128> FromStr for RangedI128<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::<i128>().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 : i128, const
MAX_DST : i128> From<RangedU8<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : u16, const MAX_SRC : u16, const MIN_DST : i128, const
MAX_DST : i128> From<RangedU16<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : u32, const MAX_SRC : u32, const MIN_DST : i128, const
MAX_DST : i128> From<RangedU32<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : u64, const MAX_SRC : u64, const MIN_DST : i128, const
MAX_DST : i128> From<RangedU64<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : u128, const MAX_SRC : u128, const MIN_DST : i128, const
MAX_DST : i128> From<RangedU128<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : usize, const MAX_SRC : usize, const MIN_DST : i128, const
MAX_DST : i128> From<RangedUsize<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : i8, const MAX_SRC : i8, const MIN_DST : i128, const
MAX_DST : i128> From<RangedI8<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : i16, const MAX_SRC : i16, const MIN_DST : i128, const
MAX_DST : i128> From<RangedI16<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : i32, const MAX_SRC : i32, const MIN_DST : i128, const
MAX_DST : i128> From<RangedI32<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : i64, const MAX_SRC : i64, const MIN_DST : i128, const
MAX_DST : i128> From<RangedI64<MIN_SRC, MAX_SRC>> for
RangedI128<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, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
impl<const MIN_SRC : isize, const MAX_SRC : isize, const MIN_DST : i128, const
MAX_DST : i128> From<RangedIsize<MIN_SRC, MAX_SRC>> for
RangedI128<MIN_DST, MAX_DST> {
#[inline(always)]
#[allow(trivial_numeric_casts, unused_comparisons)]
fn from(value: RangedIsize<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 (isize::MIN == 0, i128::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 { RangedI128::new_unchecked(value.get() as i128) }
}
}
#[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) -> Self {
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_fields_are_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: &Self) -> ::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) -> Self {
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_fields_are_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 subtraction. 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 multiplication. 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 division. 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
///
/// `rhs` 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
///
/// `rhs` 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 safety invariants are
/// upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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 safety
/// invariants are upheld.
///
/// # Safety
///
/// `rhs` must not be zero, the division must not overflow, and the result must be in
/// range.
#[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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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
///
/// `rhs` must be less than the number of bits in the inner integer type, 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_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`, 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)
}
}
}
/// Calculates self + rhs.
///
/// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_add(self, rhs: isize) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == isize::MIN && MAX == isize::MAX {
let (res, overflow) = self.get().overflowing_add(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_add(rhs) {
(res, false)
} else { (self.wrapping_add(rhs), true) }
}
/// Calculates self - rhs.
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
/// If an overflow would have occurred then the wrapped value is returned.
#[must_use =
"this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn overflowing_sub(self, rhs: isize) -> (Self, bool) {
const {
if !(MIN <= MAX) {
::core::panicking::panic("assertion failed: MIN <= MAX")
};
}
if MIN == isize::MIN && MAX == isize::MAX {
let (res, overflow) = self.get().overflowing_sub(rhs);
return (unsafe { Self::new_unchecked(res) }, overflow)
}
if let Some(res) = self.checked_sub(rhs) {
(res, false)
} else { (self.wrapping_sub(rhs), true) }
}
}
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> 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.get().map(|value| value.get()) ==
other.get().map(|value| value.get())
}
}
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! {
1832RangedU8 {
1833 mod_name: ranged_u8
1834 alias: ru81835 internal: u8
1836 signed: false
1837unsigned: u8
1838 optional: OptionRangedU81839 optional_alias: Option_ru81840 from: [
1841 RangedU16(u16)
1842 RangedU32(u32)
1843 RangedU64(u64)
1844 RangedU128(u128)
1845 RangedUsize(usize)
1846 RangedI8(i8)
1847 RangedI16(i16)
1848 RangedI32(i32)
1849 RangedI64(i64)
1850 RangedI128(i128)
1851 RangedIsize(isize)
1852 ]
1853 }
1854RangedU16 {
1855 mod_name: ranged_u16
1856 alias: ru161857 internal: u16
1858 signed: false
1859unsigned: u16
1860 optional: OptionRangedU161861 optional_alias: Option_ru161862 from: [
1863 RangedU8(u8)
1864 RangedU32(u32)
1865 RangedU64(u64)
1866 RangedU128(u128)
1867 RangedUsize(usize)
1868 RangedI8(i8)
1869 RangedI16(i16)
1870 RangedI32(i32)
1871 RangedI64(i64)
1872 RangedI128(i128)
1873 RangedIsize(isize)
1874 ]
1875 }
1876RangedU32 {
1877 mod_name: ranged_u32
1878 alias: ru321879 internal: u32
1880 signed: false
1881unsigned: u32
1882 optional: OptionRangedU321883 optional_alias: Option_ru321884 from: [
1885 RangedU8(u8)
1886 RangedU16(u16)
1887 RangedU64(u64)
1888 RangedU128(u128)
1889 RangedUsize(usize)
1890 RangedI8(i8)
1891 RangedI16(i16)
1892 RangedI32(i32)
1893 RangedI64(i64)
1894 RangedI128(i128)
1895 RangedIsize(isize)
1896 ]
1897 }
1898RangedU64 {
1899 mod_name: ranged_u64
1900 alias: ru641901 internal: u64
1902 signed: false
1903unsigned: u64
1904 optional: OptionRangedU641905 optional_alias: Option_ru641906 from: [
1907 RangedU8(u8)
1908 RangedU16(u16)
1909 RangedU32(u32)
1910 RangedU128(u128)
1911 RangedUsize(usize)
1912 RangedI8(i8)
1913 RangedI16(i16)
1914 RangedI32(i32)
1915 RangedI64(i64)
1916 RangedI128(i128)
1917 RangedIsize(isize)
1918 ]
1919 }
1920RangedU128 {
1921 mod_name: ranged_u128
1922 alias: ru1281923 internal: u128
1924 signed: false
1925unsigned: u128
1926 optional: OptionRangedU1281927 optional_alias: Option_ru1281928 from: [
1929 RangedU8(u8)
1930 RangedU16(u16)
1931 RangedU32(u32)
1932 RangedU64(u64)
1933 RangedUsize(usize)
1934 RangedI8(i8)
1935 RangedI16(i16)
1936 RangedI32(i32)
1937 RangedI64(i64)
1938 RangedI128(i128)
1939 RangedIsize(isize)
1940 ]
1941 }
1942RangedUsize {
1943 mod_name: ranged_usize
1944 alias: rusize1945 internal: usize
1946 signed: false
1947unsigned: usize
1948 optional: OptionRangedUsize1949 optional_alias: Option_rusize1950 from: [
1951 RangedU8(u8)
1952 RangedU16(u16)
1953 RangedU32(u32)
1954 RangedU64(u64)
1955 RangedU128(u128)
1956 RangedI8(i8)
1957 RangedI16(i16)
1958 RangedI32(i32)
1959 RangedI64(i64)
1960 RangedI128(i128)
1961 RangedIsize(isize)
1962 ]
1963 manual: [rand_09 rand_010]
1964 }
1965RangedI8 {
1966 mod_name: ranged_i8
1967 alias: ri81968 internal: i8
1969 signed: true
1970unsigned: u8
1971 optional: OptionRangedI81972 optional_alias: Option_ri81973 from: [
1974 RangedU8(u8)
1975 RangedU16(u16)
1976 RangedU32(u32)
1977 RangedU64(u64)
1978 RangedU128(u128)
1979 RangedUsize(usize)
1980 RangedI16(i16)
1981 RangedI32(i32)
1982 RangedI64(i64)
1983 RangedI128(i128)
1984 RangedIsize(isize)
1985 ]
1986 }
1987RangedI16 {
1988 mod_name: ranged_i16
1989 alias: ri161990 internal: i16
1991 signed: true
1992unsigned: u16
1993 optional: OptionRangedI161994 optional_alias: Option_ri161995 from: [
1996 RangedU8(u8)
1997 RangedU16(u16)
1998 RangedU32(u32)
1999 RangedU64(u64)
2000 RangedU128(u128)
2001 RangedUsize(usize)
2002 RangedI8(i8)
2003 RangedI32(i32)
2004 RangedI64(i64)
2005 RangedI128(i128)
2006 RangedIsize(isize)
2007 ]
2008 }
2009RangedI32 {
2010 mod_name: ranged_i32
2011 alias: ri322012 internal: i32
2013 signed: true
2014unsigned: u32
2015 optional: OptionRangedI322016 optional_alias: Option_ri322017 from: [
2018 RangedU8(u8)
2019 RangedU16(u16)
2020 RangedU32(u32)
2021 RangedU64(u64)
2022 RangedU128(u128)
2023 RangedUsize(usize)
2024 RangedI8(i8)
2025 RangedI16(i16)
2026 RangedI64(i64)
2027 RangedI128(i128)
2028 RangedIsize(isize)
2029 ]
2030 }
2031RangedI64 {
2032 mod_name: ranged_i64
2033 alias: ri642034 internal: i64
2035 signed: true
2036unsigned: u64
2037 optional: OptionRangedI642038 optional_alias: Option_ri642039 from: [
2040 RangedU8(u8)
2041 RangedU16(u16)
2042 RangedU32(u32)
2043 RangedU64(u64)
2044 RangedU128(u128)
2045 RangedUsize(usize)
2046 RangedI8(i8)
2047 RangedI16(i16)
2048 RangedI32(i32)
2049 RangedI128(i128)
2050 RangedIsize(isize)
2051 ]
2052 }
2053RangedI128 {
2054 mod_name: ranged_i128
2055 alias: ri1282056 internal: i128
2057 signed: true
2058unsigned: u128
2059 optional: OptionRangedI1282060 optional_alias: Option_ri1282061 from: [
2062 RangedU8(u8)
2063 RangedU16(u16)
2064 RangedU32(u32)
2065 RangedU64(u64)
2066 RangedU128(u128)
2067 RangedUsize(usize)
2068 RangedI8(i8)
2069 RangedI16(i16)
2070 RangedI32(i32)
2071 RangedI64(i64)
2072 RangedIsize(isize)
2073 ]
2074 }
2075RangedIsize {
2076 mod_name: ranged_isize
2077 alias: risize2078 internal: isize
2079 signed: true
2080unsigned: usize
2081 optional: OptionRangedIsize2082 optional_alias: Option_risize2083 from: [
2084 RangedU8(u8)
2085 RangedU16(u16)
2086 RangedU32(u32)
2087 RangedU64(u64)
2088 RangedU128(u128)
2089 RangedUsize(usize)
2090 RangedI8(i8)
2091 RangedI16(i16)
2092 RangedI32(i32)
2093 RangedI64(i64)
2094 RangedI128(i128)
2095 ]
2096 manual: [rand_09 rand_010]
2097 }
2098}20992100#[cfg(feature = "rand09")]
2101impl<const MIN: usize, const MAX: usize> rand09::distr::Distribution<RangedUsize<MIN, MAX>>
2102for rand09::distr::StandardUniform
2103{
2104#[inline]
2105fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
2106const {
2107assert!(MIN <= MAX);
2108 }
21092110#[cfg(target_pointer_width = "16")]
2111let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
2112#[cfg(target_pointer_width = "32")]
2113let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
2114#[cfg(target_pointer_width = "64")]
2115let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
2116#[cfg(not(any(
2117 target_pointer_width = "16",
2118 target_pointer_width = "32",
2119 target_pointer_width = "64"
2120)))]
2121compile_error("platform has unusual (and unsupported) pointer width");
21222123 RangedUsize::new(value).expect("rand failed to generate a valid value")
2124 }
2125}
21262127#[cfg(feature = "rand09")]
2128impl<const MIN: isize, const MAX: isize> rand09::distr::Distribution<RangedIsize<MIN, MAX>>
2129for rand09::distr::StandardUniform
2130{
2131#[inline]
2132fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
2133const {
2134assert!(MIN <= MAX);
2135 }
21362137#[cfg(target_pointer_width = "16")]
2138let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
2139#[cfg(target_pointer_width = "32")]
2140let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
2141#[cfg(target_pointer_width = "64")]
2142let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
2143#[cfg(not(any(
2144 target_pointer_width = "16",
2145 target_pointer_width = "32",
2146 target_pointer_width = "64"
2147)))]
2148compile_error("platform has unusual (and unsupported) pointer width");
21492150 RangedIsize::new(value).expect("rand failed to generate a valid value")
2151 }
2152}
21532154#[cfg(feature = "rand010")]
2155impl<const MIN: usize, const MAX: usize> rand010::distr::Distribution<RangedUsize<MIN, MAX>>
2156for rand010::distr::StandardUniform
2157{
2158#[inline]
2159fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
2160const {
2161assert!(MIN <= MAX);
2162 }
21632164use rand010::RngExt as _;
21652166#[cfg(target_pointer_width = "16")]
2167let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
2168#[cfg(target_pointer_width = "32")]
2169let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
2170#[cfg(target_pointer_width = "64")]
2171let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
2172#[cfg(not(any(
2173 target_pointer_width = "16",
2174 target_pointer_width = "32",
2175 target_pointer_width = "64"
2176)))]
2177compile_error("platform has unusual (and unsupported) pointer width");
21782179 RangedUsize::new(value).expect("rand failed to generate a valid value")
2180 }
2181}
21822183#[cfg(feature = "rand010")]
2184impl<const MIN: isize, const MAX: isize> rand010::distr::Distribution<RangedIsize<MIN, MAX>>
2185for rand010::distr::StandardUniform
2186{
2187#[inline]
2188fn sample<R: rand010::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
2189const {
2190assert!(MIN <= MAX);
2191 }
21922193use rand010::RngExt as _;
21942195#[cfg(target_pointer_width = "16")]
2196let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
2197#[cfg(target_pointer_width = "32")]
2198let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
2199#[cfg(target_pointer_width = "64")]
2200let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
2201#[cfg(not(any(
2202 target_pointer_width = "16",
2203 target_pointer_width = "32",
2204 target_pointer_width = "64"
2205)))]
2206compile_error("platform has unusual (and unsupported) pointer width");
22072208 RangedIsize::new(value).expect("rand failed to generate a valid value")
2209 }
2210}