Skip to content

Commit e8c1926

Browse files
authored
Merge pull request #334 from acrrd/support_nonzero
Implement Bounded, ToPrimitive, NumCast, FromPrimitive for NonZero*
2 parents 6f4bfba + 1896570 commit e8c1926

File tree

3 files changed

+482
-22
lines changed

3 files changed

+482
-22
lines changed

src/bounds.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
use core::num::Wrapping;
2+
use core::num::{
3+
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
4+
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
5+
};
26
use core::{f32, f64};
37
use core::{i128, i16, i32, i64, i8, isize};
48
use core::{u128, u16, u32, u64, u8, usize};
@@ -68,6 +72,49 @@ bounded_impl!(i32, i32::MIN, i32::MAX);
6872
bounded_impl!(i64, i64::MIN, i64::MAX);
6973
bounded_impl!(i128, i128::MIN, i128::MAX);
7074

75+
macro_rules! bounded_impl_nonzero_const {
76+
($t:ty, $v:expr, $i:ident) => {
77+
const $i: $t = match <$t>::new($v) {
78+
Some(nz) => nz,
79+
None => panic!("bad nonzero bound!"),
80+
};
81+
};
82+
}
83+
84+
macro_rules! bounded_impl_nonzero {
85+
($t:ty, $min:expr, $max:expr) => {
86+
impl Bounded for $t {
87+
#[inline]
88+
fn min_value() -> $t {
89+
// when MSRV is 1.70 we can use $t::MIN
90+
bounded_impl_nonzero_const!($t, $min, MIN);
91+
MIN
92+
}
93+
94+
#[inline]
95+
fn max_value() -> $t {
96+
// when MSRV is 1.70 we can use $t::MAX
97+
bounded_impl_nonzero_const!($t, $max, MAX);
98+
MAX
99+
}
100+
}
101+
};
102+
}
103+
104+
bounded_impl_nonzero!(NonZeroUsize, 1, usize::MAX);
105+
bounded_impl_nonzero!(NonZeroU8, 1, u8::MAX);
106+
bounded_impl_nonzero!(NonZeroU16, 1, u16::MAX);
107+
bounded_impl_nonzero!(NonZeroU32, 1, u32::MAX);
108+
bounded_impl_nonzero!(NonZeroU64, 1, u64::MAX);
109+
bounded_impl_nonzero!(NonZeroU128, 1, u128::MAX);
110+
111+
bounded_impl_nonzero!(NonZeroIsize, isize::MIN, isize::MAX);
112+
bounded_impl_nonzero!(NonZeroI8, i8::MIN, i8::MAX);
113+
bounded_impl_nonzero!(NonZeroI16, i16::MIN, i16::MAX);
114+
bounded_impl_nonzero!(NonZeroI32, i32::MIN, i32::MAX);
115+
bounded_impl_nonzero!(NonZeroI64, i64::MIN, i64::MAX);
116+
bounded_impl_nonzero!(NonZeroI128, i128::MIN, i128::MAX);
117+
71118
impl<T: Bounded> Bounded for Wrapping<T> {
72119
fn min_value() -> Self {
73120
Wrapping(T::min_value())
@@ -146,3 +193,37 @@ fn wrapping_is_bounded() {
146193
require_bounded(&Wrapping(42_u32));
147194
require_bounded(&Wrapping(-42));
148195
}
196+
197+
#[test]
198+
fn bounded_unsigned_nonzero() {
199+
macro_rules! test_bounded_impl_unsigned_nonzero {
200+
($t:ty, $base_ty:ty) => {
201+
assert_eq!(<$t as Bounded>::min_value().get(), 1);
202+
assert_eq!(<$t as Bounded>::max_value().get(), <$base_ty>::MAX);
203+
};
204+
}
205+
206+
test_bounded_impl_unsigned_nonzero!(NonZeroUsize, usize);
207+
test_bounded_impl_unsigned_nonzero!(NonZeroU8, u8);
208+
test_bounded_impl_unsigned_nonzero!(NonZeroU16, u16);
209+
test_bounded_impl_unsigned_nonzero!(NonZeroU32, u32);
210+
test_bounded_impl_unsigned_nonzero!(NonZeroU64, u64);
211+
test_bounded_impl_unsigned_nonzero!(NonZeroU128, u128);
212+
}
213+
214+
#[test]
215+
fn bounded_signed_nonzero() {
216+
macro_rules! test_bounded_impl_signed_nonzero {
217+
($t:ty, $base_ty:ty) => {
218+
assert_eq!(<$t as Bounded>::min_value().get(), <$base_ty>::MIN);
219+
assert_eq!(<$t as Bounded>::max_value().get(), <$base_ty>::MAX);
220+
};
221+
}
222+
223+
test_bounded_impl_signed_nonzero!(NonZeroIsize, isize);
224+
test_bounded_impl_signed_nonzero!(NonZeroI8, i8);
225+
test_bounded_impl_signed_nonzero!(NonZeroI16, i16);
226+
test_bounded_impl_signed_nonzero!(NonZeroI32, i32);
227+
test_bounded_impl_signed_nonzero!(NonZeroI64, i64);
228+
test_bounded_impl_signed_nonzero!(NonZeroI128, i128);
229+
}

src/cast.rs

Lines changed: 164 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use core::mem::size_of;
22
use core::num::Wrapping;
3+
use core::num::{
4+
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
5+
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
6+
};
37
use core::{f32, f64};
48
use core::{i128, i16, i32, i64, i8, isize};
59
use core::{u128, u16, u32, u64, u8, usize};
@@ -126,9 +130,8 @@ pub trait ToPrimitive {
126130
}
127131

128132
macro_rules! impl_to_primitive_int_to_int {
129-
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
133+
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
130134
#[inline]
131-
$(#[$cfg])*
132135
fn $method(&self) -> Option<$DstT> {
133136
let min = $DstT::MIN as $SrcT;
134137
let max = $DstT::MAX as $SrcT;
@@ -142,9 +145,8 @@ macro_rules! impl_to_primitive_int_to_int {
142145
}
143146

144147
macro_rules! impl_to_primitive_int_to_uint {
145-
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
148+
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
146149
#[inline]
147-
$(#[$cfg])*
148150
fn $method(&self) -> Option<$DstT> {
149151
let max = $DstT::MAX as $SrcT;
150152
if 0 <= *self && (size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max) {
@@ -197,9 +199,8 @@ impl_to_primitive_int!(i64);
197199
impl_to_primitive_int!(i128);
198200

199201
macro_rules! impl_to_primitive_uint_to_int {
200-
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
202+
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
201203
#[inline]
202-
$(#[$cfg])*
203204
fn $method(&self) -> Option<$DstT> {
204205
let max = $DstT::MAX as $SrcT;
205206
if size_of::<$SrcT>() < size_of::<$DstT>() || *self <= max {
@@ -212,9 +213,8 @@ macro_rules! impl_to_primitive_uint_to_int {
212213
}
213214

214215
macro_rules! impl_to_primitive_uint_to_uint {
215-
($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
216+
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
216217
#[inline]
217-
$(#[$cfg])*
218218
fn $method(&self) -> Option<$DstT> {
219219
let max = $DstT::MAX as $SrcT;
220220
if size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max {
@@ -266,6 +266,54 @@ impl_to_primitive_uint!(u32);
266266
impl_to_primitive_uint!(u64);
267267
impl_to_primitive_uint!(u128);
268268

269+
macro_rules! impl_to_primitive_nonzero_to_method {
270+
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
271+
#[inline]
272+
fn $method(&self) -> Option<$DstT> {
273+
self.get().$method()
274+
}
275+
)*}
276+
}
277+
278+
macro_rules! impl_to_primitive_nonzero {
279+
($T:ident) => {
280+
impl ToPrimitive for $T {
281+
impl_to_primitive_nonzero_to_method! { $T:
282+
fn to_isize -> isize;
283+
fn to_i8 -> i8;
284+
fn to_i16 -> i16;
285+
fn to_i32 -> i32;
286+
fn to_i64 -> i64;
287+
fn to_i128 -> i128;
288+
289+
fn to_usize -> usize;
290+
fn to_u8 -> u8;
291+
fn to_u16 -> u16;
292+
fn to_u32 -> u32;
293+
fn to_u64 -> u64;
294+
fn to_u128 -> u128;
295+
296+
fn to_f32 -> f32;
297+
fn to_f64 -> f64;
298+
}
299+
}
300+
};
301+
}
302+
303+
impl_to_primitive_nonzero!(NonZeroUsize);
304+
impl_to_primitive_nonzero!(NonZeroU8);
305+
impl_to_primitive_nonzero!(NonZeroU16);
306+
impl_to_primitive_nonzero!(NonZeroU32);
307+
impl_to_primitive_nonzero!(NonZeroU64);
308+
impl_to_primitive_nonzero!(NonZeroU128);
309+
310+
impl_to_primitive_nonzero!(NonZeroIsize);
311+
impl_to_primitive_nonzero!(NonZeroI8);
312+
impl_to_primitive_nonzero!(NonZeroI16);
313+
impl_to_primitive_nonzero!(NonZeroI32);
314+
impl_to_primitive_nonzero!(NonZeroI64);
315+
impl_to_primitive_nonzero!(NonZeroI128);
316+
269317
macro_rules! impl_to_primitive_float_to_float {
270318
($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
271319
#[inline]
@@ -286,9 +334,8 @@ macro_rules! float_to_int_unchecked {
286334
}
287335

288336
macro_rules! impl_to_primitive_float_to_signed_int {
289-
($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
337+
($f:ident : $( fn $method:ident -> $i:ident ; )*) => {$(
290338
#[inline]
291-
$(#[$cfg])*
292339
fn $method(&self) -> Option<$i> {
293340
// Float as int truncates toward zero, so we want to allow values
294341
// in the exclusive range `(MIN-1, MAX+1)`.
@@ -316,9 +363,8 @@ macro_rules! impl_to_primitive_float_to_signed_int {
316363
}
317364

318365
macro_rules! impl_to_primitive_float_to_unsigned_int {
319-
($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $u:ident ; )*) => {$(
366+
($f:ident : $( fn $method:ident -> $u:ident ; )*) => {$(
320367
#[inline]
321-
$(#[$cfg])*
322368
fn $method(&self) -> Option<$u> {
323369
// Float as int truncates toward zero, so we want to allow values
324370
// in the exclusive range `(-1, MAX+1)`.
@@ -493,7 +539,6 @@ pub trait FromPrimitive: Sized {
493539

494540
macro_rules! impl_from_primitive {
495541
($T:ty, $to_ty:ident) => {
496-
#[allow(deprecated)]
497542
impl FromPrimitive for $T {
498543
#[inline]
499544
fn from_isize(n: isize) -> Option<$T> {
@@ -572,10 +617,87 @@ impl_from_primitive!(u128, to_u128);
572617
impl_from_primitive!(f32, to_f32);
573618
impl_from_primitive!(f64, to_f64);
574619

620+
macro_rules! impl_from_primitive_nonzero {
621+
($T:ty, $to_ty:ident) => {
622+
impl FromPrimitive for $T {
623+
#[inline]
624+
fn from_isize(n: isize) -> Option<$T> {
625+
n.$to_ty().and_then(Self::new)
626+
}
627+
#[inline]
628+
fn from_i8(n: i8) -> Option<$T> {
629+
n.$to_ty().and_then(Self::new)
630+
}
631+
#[inline]
632+
fn from_i16(n: i16) -> Option<$T> {
633+
n.$to_ty().and_then(Self::new)
634+
}
635+
#[inline]
636+
fn from_i32(n: i32) -> Option<$T> {
637+
n.$to_ty().and_then(Self::new)
638+
}
639+
#[inline]
640+
fn from_i64(n: i64) -> Option<$T> {
641+
n.$to_ty().and_then(Self::new)
642+
}
643+
#[inline]
644+
fn from_i128(n: i128) -> Option<$T> {
645+
n.$to_ty().and_then(Self::new)
646+
}
647+
648+
#[inline]
649+
fn from_usize(n: usize) -> Option<$T> {
650+
n.$to_ty().and_then(Self::new)
651+
}
652+
#[inline]
653+
fn from_u8(n: u8) -> Option<$T> {
654+
n.$to_ty().and_then(Self::new)
655+
}
656+
#[inline]
657+
fn from_u16(n: u16) -> Option<$T> {
658+
n.$to_ty().and_then(Self::new)
659+
}
660+
#[inline]
661+
fn from_u32(n: u32) -> Option<$T> {
662+
n.$to_ty().and_then(Self::new)
663+
}
664+
#[inline]
665+
fn from_u64(n: u64) -> Option<$T> {
666+
n.$to_ty().and_then(Self::new)
667+
}
668+
#[inline]
669+
fn from_u128(n: u128) -> Option<$T> {
670+
n.$to_ty().and_then(Self::new)
671+
}
672+
673+
#[inline]
674+
fn from_f32(n: f32) -> Option<$T> {
675+
n.$to_ty().and_then(Self::new)
676+
}
677+
#[inline]
678+
fn from_f64(n: f64) -> Option<$T> {
679+
n.$to_ty().and_then(Self::new)
680+
}
681+
}
682+
};
683+
}
684+
685+
impl_from_primitive_nonzero!(NonZeroIsize, to_isize);
686+
impl_from_primitive_nonzero!(NonZeroI8, to_i8);
687+
impl_from_primitive_nonzero!(NonZeroI16, to_i16);
688+
impl_from_primitive_nonzero!(NonZeroI32, to_i32);
689+
impl_from_primitive_nonzero!(NonZeroI64, to_i64);
690+
impl_from_primitive_nonzero!(NonZeroI128, to_i128);
691+
impl_from_primitive_nonzero!(NonZeroUsize, to_usize);
692+
impl_from_primitive_nonzero!(NonZeroU8, to_u8);
693+
impl_from_primitive_nonzero!(NonZeroU16, to_u16);
694+
impl_from_primitive_nonzero!(NonZeroU32, to_u32);
695+
impl_from_primitive_nonzero!(NonZeroU64, to_u64);
696+
impl_from_primitive_nonzero!(NonZeroU128, to_u128);
697+
575698
macro_rules! impl_to_primitive_wrapping {
576-
($( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
699+
($( fn $method:ident -> $i:ident ; )*) => {$(
577700
#[inline]
578-
$(#[$cfg])*
579701
fn $method(&self) -> Option<$i> {
580702
(self.0).$method()
581703
}
@@ -604,9 +726,8 @@ impl<T: ToPrimitive> ToPrimitive for Wrapping<T> {
604726
}
605727

606728
macro_rules! impl_from_primitive_wrapping {
607-
($( $(#[$cfg:meta])* fn $method:ident ( $i:ident ); )*) => {$(
729+
($( fn $method:ident ( $i:ident ); )*) => {$(
608730
#[inline]
609-
$(#[$cfg])*
610731
fn $method(n: $i) -> Option<Self> {
611732
T::$method(n).map(Wrapping)
612733
}
@@ -670,10 +791,7 @@ macro_rules! impl_num_cast {
670791
($T:ty, $conv:ident) => {
671792
impl NumCast for $T {
672793
#[inline]
673-
#[allow(deprecated)]
674794
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
675-
// `$conv` could be generated using `concat_idents!`, but that
676-
// macro seems to be broken at the moment
677795
n.$conv()
678796
}
679797
}
@@ -695,6 +813,31 @@ impl_num_cast!(isize, to_isize);
695813
impl_num_cast!(f32, to_f32);
696814
impl_num_cast!(f64, to_f64);
697815

816+
macro_rules! impl_num_cast_nonzero {
817+
($T:ty, $conv:ident) => {
818+
impl NumCast for $T {
819+
#[inline]
820+
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
821+
n.$conv().and_then(Self::new)
822+
}
823+
}
824+
};
825+
}
826+
827+
impl_num_cast_nonzero!(NonZeroUsize, to_usize);
828+
impl_num_cast_nonzero!(NonZeroU8, to_u8);
829+
impl_num_cast_nonzero!(NonZeroU16, to_u16);
830+
impl_num_cast_nonzero!(NonZeroU32, to_u32);
831+
impl_num_cast_nonzero!(NonZeroU64, to_u64);
832+
impl_num_cast_nonzero!(NonZeroU128, to_u128);
833+
834+
impl_num_cast_nonzero!(NonZeroIsize, to_isize);
835+
impl_num_cast_nonzero!(NonZeroI8, to_i8);
836+
impl_num_cast_nonzero!(NonZeroI16, to_i16);
837+
impl_num_cast_nonzero!(NonZeroI32, to_i32);
838+
impl_num_cast_nonzero!(NonZeroI64, to_i64);
839+
impl_num_cast_nonzero!(NonZeroI128, to_i128);
840+
698841
impl<T: NumCast> NumCast for Wrapping<T> {
699842
fn from<U: ToPrimitive>(n: U) -> Option<Self> {
700843
T::from(n).map(Wrapping)
@@ -736,8 +879,7 @@ where
736879
}
737880

738881
macro_rules! impl_as_primitive {
739-
(@ $T: ty => $(#[$cfg:meta])* impl $U: ty ) => {
740-
$(#[$cfg])*
882+
(@ $T: ty => impl $U: ty ) => {
741883
impl AsPrimitive<$U> for $T {
742884
#[inline] fn as_(self) -> $U { self as $U }
743885
}

0 commit comments

Comments
 (0)