Crates.io | comfy-bounded-ints |
lib.rs | comfy-bounded-ints |
version | 0.2.1 |
source | src |
created_at | 2024-01-10 02:33:46.64113 |
updated_at | 2024-05-11 20:47:30.016567 |
description | Bounded-integer types focused on ergonomics and safety. (See README.md) |
homepage | |
repository | https://github.com/Houtamelo/comfy-bounded-ints |
max_upload_size | |
id | 1094852 |
size | 36,097,944 |
The goal of this crate is to allow users to fearlessly use bounded integers without worrying about checking the operations performed on them.
There is one exception: division by zero will still panic.
.get()
or the deref
*
operator.Hash
/PartialOrd
/Ord
traits are not covered by unit tests.All features are disabled by default.
div_assign_zero
: Enables unchecked division by zero. (Division by non-zero types (NonZeroI8, ...) is provided without this feature).serde
: Enables serde Serialization/Deserialization support, all bounded types are serialized transparently as their inner value.
Example: assert_eq!(serde_json::to_string(&Bound_i8::<0, 10>::new(5)).unwrap(), serde_json::to_string(&5_i8).unwrap())
.use comfy_bounded_ints::{
Bound_i8, Bound_i16, Bound_i32, Bound_i64, Bound_i128, Bound_isize,
Bound_u8, Bound_u16, Bound_u32, Bound_u64, Bound_u128, Bound_usize
};
Use the new
function to create a new bounded type.
cargo build
will not compile if MIN > MAX
use comfy_bounded_ints::Bound_i16;
let bounded = Bound_i16::<20, 50>::new(30);
^^^^^^
No operations can violate this rule.
use comfy_bounded_ints::Bound_i32;
let bounded = Bound_i32::<20, 50>::new(80);
assert_eq!(bounded.get(), 50);
^^^^^^^^^^^^^^^^^
let bounded = Bound_i32::<20, 50>::new(10);
assert_eq!(bounded.get(), 20);
^^^^^^^^^^^^^^^^^
.get()
method or the deref
*
operatoruse comfy_bounded_ints::Bound_i64;
let bounded = Bound_i64::<20, 50>::new(30);
assert_eq!(bounded.get(), 30);
^^^^^^
assert_eq!(*bounded, 30);
^
DerefMut
, as this would allow violating the constraints.If you want to mutate the inner value, you can use the .set()
method, or any of the assign operators.
use comfy_bounded_ints::Bound_isize;
let mut bounded = Bound_isize::<20, 50>::new(30);
bounded.set(40);
^^^^^^^^
assert_eq!(bounded.get(), 40);
bounded += 10;
^^
assert_eq!(bounded.get(), 50);
bounded.set(10);
^^^^^^^^
assert_eq!(bounded.get(), 20);
bounded.set(80);
^^^^^^^^
assert_eq!(bounded.get(), 50);
bounded -= 10;
^^
assert_eq!(bounded.get(), 40);
bounded /= 2;
^^
assert_eq!(bounded.get(), 20);
bounded *= 2;
^^
assert_eq!(bounded.get(), 40);
bounded %= 30;
^^
assert_eq!(bounded.get(), 20);
AddAssign
/SubAssign
/MulAssign
/DivAssign
/RemAssign
Are allowed between different integer types, as well as bounded types with different constraints.
The regular Add
/Sub
/Mul
/Div
/Rem
operations are not supported, use .get
or *
deref
to perform them on the inner value instead.
Support for the regular operations is not provided due to ambiguity in which type should be returned.
use comfy_bounded_ints::{Bound_i8, Bound_i16, Bound_u8, Bound_u32, Bound_isize};
let mut bounded_i8 = Bound_i8::<20, 50>::new(30);
let bounded_i16 = Bound_i16::< -200, 500>::new(-200);
bounded_i8 += bounded_i16;
^^
assert_eq!(bounded_i8.get(), 20);
let mut bounded_i8 = Bound_i8::< -128, 127>::new(-128);
let bounded_i16 = Bound_i16::< -300, 500>::new(-300);
bounded_i8 -= bounded_i16;
^^
assert_eq!(bounded_i8.get(), 127);
let mut bounded_u8 = Bound_u8::< 5, 80>::new(70);
let bounded_i16 = Bound_i16::< -300, 500>::new(-1);
bounded_u8 *= bounded_i16;
^^
assert_eq!(bounded_u8.get(), 5);
let mut bounded_u32 = Bound_u8::< 2, 650>::new(800);
let bounded_i8 = Bound_i8::< -30, 10>::new(-1);
bounded_u32 /= bounded_i8;
^^
assert_eq!(bounded_u32.get(), 2);
let mut bounded_u32 = Bound_u32::< 3, 650>::new(800);
let bounded_i8 = Bound_i8::< -30, 10>::new(-1);
bounded_u32 %= bounded_i8;
^^
assert_eq!(bounded_u32.get(), 3);
let mut bounded_isize = Bound_isize::<0, 200>::new(80);
let int_i8 = 30_i8;
bounded_isize += int_i8;
^^
assert_eq!(bounded_isize.get(), 110);
let mut bounded_isize = Bound_isize::<0, 200>::new(80);
let int_i32 = -900_i32;
bounded_isize += int_i32;
^^
assert_eq!(bounded_isize.get(), 0);
...
Default
trait is implemented for all bounded typesIt creates a new bounded type with the minimum value as the inner value.
This does not require the div_assign_zero
feature.
use comfy_bounded_ints::{Bound_i8, Bound_u128};
let mut bounded_i8 = Bound_i8::< -30, 80>::new(-120);
let non_zero_i8 = NonZeroI8::new(-2).unwrap();
bounded_i8 *= non_zero_i8;
^^
assert_eq!(bounded_i8.get(), 60);
let mut bounded_u128 = Bound_u128::< 3, 650>::new(800);
let non_zero_u128 = NonZeroU128::new(2).unwrap();
bounded_u128 /= non_zero_u128;
^^
assert_eq!(bounded_u128.get(), 325);
From
traitThis trait also provides a blanket implementation allowing any integer to be converted to a given bounded type using the method .into()
.
use comfy_bounded_ints::{Bound_i8, Bound_isize, Bound_u8, Bound_u32};
let bounded_i8 = Bound_i8::< -30, 80>::from(-120_i8);
^^^^^^^^^^^^^
assert_eq!(bounded_i8.get(), -30);
let bounded_u32 = Bound_u32::< 2, 650>::from(-800_i32);
^^^^^^^^^^^^^^
assert_eq!(bounded_u32.get(), 2);
let bounded_isize: Bound_isize<20, 100> = 50_u128.into();
^^^^^^^
assert_eq!(bounded_isize.get(), 50);
let bounded_u8: Bound_u8<20, 100> = -50_i64.into();
^^^^^^^
assert_eq!(bounded_u8.get(), 20);
Constraints are irrelevant for this comparison.
For other comparisons, you can use the .get()
method or the deref
*
operator, then compare using the inner values.
use comfy_bounded_ints::{Bound_i8, Bound_u16};
let a_i8 = Bound_i8::< -30, 80>::new(-120);
let b_i8 = Bound_i8::< -30, 80>::new(20);
assert!(a_i8 != b_i8);
let a_u16 = Bound_u16::< 2, 650>::new(800);
let b_u16 = Bound_u16::< 2, 650>::new(650);
assert!(a_u16 == b_u16);