arbitrary/foreign/core/
num.rs

1use {
2    crate::{Arbitrary, Error, MaxRecursionReached, Result, Unstructured},
3    core::{
4        mem,
5        num::{
6            NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
7            NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
8        },
9    },
10};
11
12macro_rules! impl_arbitrary_for_integers {
13    ( $( $ty:ty; )* ) => {
14        $(
15            impl<'a> Arbitrary<'a> for $ty {
16                fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
17                    let mut buf = [0; mem::size_of::<$ty>()];
18                    u.fill_buffer(&mut buf)?;
19                    Ok(Self::from_le_bytes(buf))
20                }
21
22                #[inline]
23                fn size_hint(_depth: usize) -> (usize, Option<usize>) {
24                    let n = mem::size_of::<$ty>();
25                    (n, Some(n))
26                }
27
28            }
29        )*
30    }
31}
32
33impl_arbitrary_for_integers! {
34    u8;
35    u16;
36    u32;
37    u64;
38    u128;
39    i8;
40    i16;
41    i32;
42    i64;
43    i128;
44}
45
46// Note: We forward Arbitrary for i/usize to i/u64 in order to simplify corpus
47// compatibility between 32-bit and 64-bit builds. This introduces dead space in
48// 32-bit builds but keeps the input layout independent of the build platform.
49impl<'a> Arbitrary<'a> for usize {
50    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
51        u.arbitrary::<u64>().map(|x| x as usize)
52    }
53
54    #[inline]
55    fn size_hint(depth: usize) -> (usize, Option<usize>) {
56        <u64 as Arbitrary>::size_hint(depth)
57    }
58}
59
60impl<'a> Arbitrary<'a> for isize {
61    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
62        u.arbitrary::<i64>().map(|x| x as isize)
63    }
64
65    #[inline]
66    fn size_hint(depth: usize) -> (usize, Option<usize>) {
67        <i64 as Arbitrary>::size_hint(depth)
68    }
69}
70
71macro_rules! impl_arbitrary_for_floats {
72    ( $( $ty:ident : $unsigned:ty; )* ) => {
73        $(
74            impl<'a> Arbitrary<'a> for $ty {
75                fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
76                    Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?))
77                }
78
79                #[inline]
80                fn size_hint(depth: usize) -> (usize, Option<usize>) {
81                    <$unsigned as Arbitrary<'a>>::size_hint(depth)
82                }
83            }
84        )*
85    }
86}
87
88impl_arbitrary_for_floats! {
89    f32: u32;
90    f64: u64;
91}
92
93macro_rules! implement_nonzero_int {
94    ($nonzero:ty, $int:ty) => {
95        impl<'a> Arbitrary<'a> for $nonzero {
96            fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
97                match Self::new(<$int as Arbitrary<'a>>::arbitrary(u)?) {
98                    Some(n) => Ok(n),
99                    None => Err(Error::IncorrectFormat),
100                }
101            }
102
103            #[inline]
104            fn size_hint(depth: usize) -> (usize, Option<usize>) {
105                <$int as Arbitrary<'a>>::size_hint(depth)
106            }
107        }
108    };
109}
110
111implement_nonzero_int! { NonZeroI8, i8 }
112implement_nonzero_int! { NonZeroI16, i16 }
113implement_nonzero_int! { NonZeroI32, i32 }
114implement_nonzero_int! { NonZeroI64, i64 }
115implement_nonzero_int! { NonZeroI128, i128 }
116implement_nonzero_int! { NonZeroIsize, isize }
117implement_nonzero_int! { NonZeroU8, u8 }
118implement_nonzero_int! { NonZeroU16, u16 }
119implement_nonzero_int! { NonZeroU32, u32 }
120implement_nonzero_int! { NonZeroU64, u64 }
121implement_nonzero_int! { NonZeroU128, u128 }
122implement_nonzero_int! { NonZeroUsize, usize }
123
124impl<'a, A> Arbitrary<'a> for Wrapping<A>
125where
126    A: Arbitrary<'a>,
127{
128    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
129        Arbitrary::arbitrary(u).map(Wrapping)
130    }
131
132    #[inline]
133    fn size_hint(depth: usize) -> (usize, Option<usize>) {
134        Self::try_size_hint(depth).unwrap_or_default()
135    }
136
137    #[inline]
138    fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), MaxRecursionReached> {
139        <A as Arbitrary<'a>>::try_size_hint(depth)
140    }
141}