diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 983bd68..3d826b9 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -13,6 +13,7 @@ pub fn derive_arbitrary(tokens: proc_macro::TokenStream) -> proc_macro::TokenStr build_arbitrary_lifetime(input.generics.clone()); let arbitrary_method = gen_arbitrary_method(&input, lifetime_without_bounds.clone()); + let dearbitrary_method = gen_dearbitrary_method(&input, lifetime_without_bounds.clone()); let size_hint_method = gen_size_hint_method(&input); let name = input.ident; // Add a bound `T: Arbitrary` to every type parameter T. @@ -31,6 +32,7 @@ pub fn derive_arbitrary(tokens: proc_macro::TokenStream) -> proc_macro::TokenStr (quote! { impl #impl_generics arbitrary::Arbitrary<#lifetime_without_bounds> for #name #ty_generics #where_clause { #arbitrary_method + #dearbitrary_method #size_hint_method } }) @@ -67,6 +69,138 @@ fn add_trait_bounds(mut generics: Generics, lifetime: LifetimeDef) -> Generics { generics } +fn gen_dearbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenStream { + let ident = &input.ident; + let dearbitrary_structlike = |fields: &syn::Fields| { + let dearbitrary = deconstruct(fields, |i, f| { + if f.ident.is_some() { + let n = &f.ident; + quote!(arbitrary::Arbitrary::dearbitrary(&self.#n)) + } else { + let a = i; + quote!(arbitrary::Arbitrary::dearbitrary(&self.#a)) + } + }); + quote! { + fn dearbitrary(&self) -> Vec { + let mut v: Vec = Vec::new(); + #dearbitrary + v + } + } + }; + match &input.data { + Data::Struct(data) => dearbitrary_structlike(&data.fields), + Data::Union(data) => dearbitrary_structlike(&Fields::Named(data.fields.clone())), + Data::Enum(data) => { + let variants = data.variants.iter().enumerate().map(|(i, variant)| { + let idx = i as u64; + let ctor = cons(&variant.fields); + let variant_name = &variant.ident; + quote! { #ident::#variant_name #ctor => #idx } + }); + + let variants2 = data.variants.iter().enumerate().map(|(i, variant)| { + let idx = i as u64; + let ctor = cons(&variant.fields); + let foo = cons2(&variant.fields); + + let variant_name = &variant.ident; + quote! { #ident::#variant_name #ctor => { #foo } } + }); + + let count = data.variants.len() as u64; + quote! { + fn dearbitrary(&self) -> Vec { + // Use a multiply + shift to generate a ranged random number + // with slight bias. For details, see: + // https://lemire.me/blog/2016/06/30/fast-random-shuffling + let mut v = Vec::new(); + let val = match self { + #(#variants,)* + _ => unreachable!() + }; + let mut x: u32 = ((val << 32) / #count ) as u32; + if ((u64::from(x) * #count) >> 32) < val { + x += 1; + } + + v.append(&mut u32::dearbitrary(&x).to_vec()); + + match self { + #(#variants2,)* + _ => unreachable!() + }; + v + } + } + } + } +} + +fn cons2(fields: &Fields) -> TokenStream { + match fields { + Fields::Named(names) => { + let names = names.named.iter().enumerate().map(|(i, f)| { + let name = f.ident.as_ref().unwrap(); + quote!(v.append(&mut arbitrary::Arbitrary::dearbitrary(#name))) + + }); + quote! { { #(#names;)* } } + } + Fields::Unnamed(names) => { + let names = names.unnamed.iter().enumerate().map(|(i, f)| { + let id = Ident::new(&format!("x{}", i), Span::call_site()); + quote!(v.append(&mut arbitrary::Arbitrary::dearbitrary(#id))) + + }); + quote! { { #(#names;)* } } + } + Fields::Unit => quote!() + } +} + +fn cons(fields: &Fields) -> TokenStream { + match fields { + Fields::Named(names) => { + let names = names.named.iter().enumerate().map(|(_, f)| { + let name = f.ident.as_ref().unwrap(); + quote! { #name } + }); + quote! { { #(#names,)* } } + } + Fields::Unnamed(names) => { + let names = names.unnamed.iter().enumerate().map(|(i, _)| { + let id = Ident::new(&format!("x{}", i), Span::call_site());; + quote! { #id } + }); + quote! { ( #(#names),* ) } + } + Fields::Unit => quote!(), + } +} + +fn deconstruct(fields: &Fields, ctor: impl Fn(usize, &Field) -> TokenStream) -> TokenStream { + match fields { + Fields::Named(names) => { + let names = names.named.iter().enumerate().map(|(i, f)| { + let name = f.ident.as_ref().unwrap(); + let ctor = ctor(i, f); + quote! { v.append(&mut #ctor) } + }); + quote! { { #(#names;)* } } + } + Fields::Unnamed(names) => { + let names = names.unnamed.iter().enumerate().map(|(i, f)| { + let ctor = ctor(i, f); + quote! { v.append(&mut #ctor) } + }); + quote! { { #(#names;)* } } + } + Fields::Unit => quote!(), + } +} + fn gen_arbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenStream { let ident = &input.ident; let arbitrary_structlike = |fields| { diff --git a/src/lib.rs b/src/lib.rs index 7b791ab..1a6b98c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,6 +128,10 @@ use std::sync::{Arc, Mutex}; /// /// Ok(my_collection) /// } +/// +/// fn dearbitrary(&self) -> Vec { +/// unimplemented!() +/// } /// } /// # } /// ``` @@ -174,6 +178,12 @@ pub trait Arbitrary<'a>: Sized { /// See also the documentation for [`Unstructured`][crate::Unstructured]. fn arbitrary(u: &mut Unstructured<'a>) -> Result; + + /// Inverse operation of `arbitrary` aka creating the byte stream, which can be used + /// together with an `arbitrary` call to recreate `Self`. + /// + fn dearbitrary(&self) -> Vec; + /// Generate an arbitrary value of `Self` from the entirety of the given unstructured data. /// /// This is similar to Arbitrary::arbitrary, however it assumes that it is the @@ -234,6 +244,10 @@ pub trait Arbitrary<'a>: Sized { /// // ... /// # unimplemented!() /// } + /// + /// fn dearbitrary(&self) -> Vec { + /// unimplemented!() + /// } /// /// fn size_hint(depth: usize) -> (usize, Option) { /// // Protect against potential infinite recursion with @@ -267,6 +281,10 @@ impl<'a> Arbitrary<'a> for () { Ok(()) } + fn dearbitrary(&self) -> Vec { + Vec::new() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) @@ -278,6 +296,14 @@ impl<'a> Arbitrary<'a> for bool { Ok(>::arbitrary(u)? & 1 == 1) } + fn dearbitrary(&self) -> Vec { + if *self { + u8::dearbitrary(&1) + } else { + u8::dearbitrary(&0) + } + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -298,6 +324,14 @@ macro_rules! impl_arbitrary_for_integers { Ok(x as $ty) } + fn dearbitrary(&self) -> Vec { + let mut buf = [0; mem::size_of::<$ty>()]; + for i in 0..mem::size_of::<$ty>() { + buf[i] = ((*self as $unsigned >> (i * 8)) & 0xFF ) as u8; + } + buf.to_vec() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { let n = mem::size_of::<$ty>(); @@ -332,6 +366,10 @@ macro_rules! impl_arbitrary_for_floats { Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?)) } + fn dearbitrary(&self) -> Vec { + <$unsigned>::dearbitrary(&Self::to_bits(*self)) + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { <$unsigned as Arbitrary<'a>>::size_hint(depth) @@ -364,6 +402,10 @@ impl<'a> Arbitrary<'a> for char { } } + fn dearbitrary(&self) -> Vec { + u32::dearbitrary(&(*self as u32)) + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -375,6 +417,10 @@ impl<'a> Arbitrary<'a> for AtomicBool { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -386,6 +432,10 @@ impl<'a> Arbitrary<'a> for AtomicIsize { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -397,6 +447,10 @@ impl<'a> Arbitrary<'a> for AtomicUsize { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -420,6 +474,10 @@ macro_rules! impl_range { Ok($fun(value, $fun_closure)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { $size_hint_closure(depth) @@ -499,6 +557,10 @@ impl<'a> Arbitrary<'a> for Duration { )) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( @@ -517,6 +579,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Option { }) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( @@ -535,6 +601,10 @@ impl<'a, A: Arbitrary<'a>, B: Arbitrary<'a>> Arbitrary<'a> for std::result::Resu }) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( @@ -547,16 +617,30 @@ impl<'a, A: Arbitrary<'a>, B: Arbitrary<'a>> Arbitrary<'a> for std::result::Resu } } +macro_rules! expr { ($x:expr) => ($x) } +macro_rules! tuple_index { + ($tuple:expr, $idx:tt) => { expr!($tuple.$idx) } +} + + macro_rules! arbitrary_tuple { () => {}; - ($last: ident $($xs: ident)*) => { - arbitrary_tuple!($($xs)*); + ($last: ident -> ($ln: tt) $($xs: ident -> ($n: tt))*) => { + arbitrary_tuple!($($xs -> ($n))*); impl<'a, $($xs: Arbitrary<'a>,)* $last: Arbitrary<'a>> Arbitrary<'a> for ($($xs,)* $last,) { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) } + fn dearbitrary(&self) -> Vec { + let mut vv: Vec> = Vec::new(); + vv.push(Arbitrary::dearbitrary(&tuple_index!(*self, $ln))); + $(vv.push(Arbitrary::dearbitrary(&tuple_index!(*self, $n)));)* + vv.reverse(); + vv.into_iter().flatten().collect() + } + #[allow(unused_mut, non_snake_case)] fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { $(let $xs = $xs::arbitrary(&mut u)?;)* @@ -574,7 +658,33 @@ macro_rules! arbitrary_tuple { } }; } -arbitrary_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z); +arbitrary_tuple!( + A -> (25) + B -> (24) + C -> (23) + D -> (22) + E -> (21) + F -> (20) + G -> (19) + H -> (18) + I -> (17) + J -> (16) + K -> (15) + L -> (14) + M -> (13) + N -> (12) + O -> (11) + P -> (10) + Q -> (9) + R -> (8) + S -> (7) + T -> (6) + U -> (5) + V -> (4) + W -> (3) + X -> (2) + Y -> (1) + Z -> (0)); // Helper to safely create arrays since the standard library doesn't // provide one yet. Shouldn't be necessary in the future. @@ -644,6 +754,10 @@ where try_create_array(|_| >::arbitrary(u)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { let mut array = Self::arbitrary(&mut u)?; @@ -667,6 +781,27 @@ impl<'a> Arbitrary<'a> for &'a [u8] { u.bytes(len) } + fn dearbitrary(&self) -> Vec { + let mut len_bytes = if self.len() <= core::u8::MAX as usize + 1 { + let l = self.len() as u8; + vec![l] + } else if self.len() <= core::u16::MAX as usize + 1 { + let l = self.len() as u16; + l.to_le_bytes().to_vec() + } else if self.len() <= core::u32::MAX as usize + 1 { + let l = self.len() as u32; + l.to_le_bytes().to_vec() + } else { + let l = self.len() as u64; + l.to_le_bytes().to_vec() + }; + + let mut v = Vec::new(); + v.append(&mut self.to_vec()); + v.append(&mut len_bytes); + v + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { Ok(u.take_rest()) } @@ -682,6 +817,16 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Vec { u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + let mut v = Vec::new(); + for a in self { + v.append(&mut bool::dearbitrary(&true)); + v.append(&mut A::dearbitrary(a)); + } + v.append(&mut bool::dearbitrary(&false)); + v + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -697,6 +842,10 @@ impl<'a, K: Arbitrary<'a> + Ord, V: Arbitrary<'a>> Arbitrary<'a> for BTreeMap Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -712,6 +861,10 @@ impl<'a, A: Arbitrary<'a> + Ord> Arbitrary<'a> for BTreeSet { u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -727,6 +880,10 @@ impl<'a, A: Arbitrary<'a> + Ord> Arbitrary<'a> for BinaryHeap { u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -744,6 +901,10 @@ impl<'a, K: Arbitrary<'a> + Eq + ::std::hash::Hash, V: Arbitrary<'a>, S: BuildHa u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -761,6 +922,10 @@ impl<'a, A: Arbitrary<'a> + Eq + ::std::hash::Hash, S: BuildHasher + Default> Ar u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -776,6 +941,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for LinkedList { u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -791,6 +960,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for VecDeque { u.arbitrary_iter()?.collect() } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } @@ -810,6 +983,10 @@ where Arbitrary::arbitrary(u).map(Cow::Owned) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, |depth| { @@ -838,6 +1015,10 @@ impl<'a> Arbitrary<'a> for &'a str { } } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { let bytes = u.take_rest(); str::from_utf8(bytes) @@ -856,6 +1037,10 @@ impl<'a> Arbitrary<'a> for String { <&str as Arbitrary>::arbitrary(u).map(Into::into) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { <&str as Arbitrary>::arbitrary_take_rest(u).map(Into::into) } @@ -874,6 +1059,10 @@ impl<'a> Arbitrary<'a> for CString { }) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { as Arbitrary>::size_hint(depth) @@ -885,6 +1074,10 @@ impl<'a> Arbitrary<'a> for OsString { ::arbitrary(u).map(From::from) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) @@ -896,6 +1089,10 @@ impl<'a> Arbitrary<'a> for PathBuf { ::arbitrary(u).map(From::from) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) @@ -904,7 +1101,12 @@ impl<'a> Arbitrary<'a> for PathBuf { impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box { fn arbitrary(u: &mut Unstructured<'a>) -> Result { - Arbitrary::arbitrary(u).map(Self::new) + let a = Arbitrary::arbitrary(u); + a.map(Self::new) + } + + fn dearbitrary(&self) -> Vec { + A::dearbitrary(&*self) } #[inline] @@ -913,11 +1115,15 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box { } } -impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<[A]> { +impl<'a, A: Arbitrary<'a> + Clone> Arbitrary<'a> for Box<[A]> { fn arbitrary(u: &mut Unstructured<'a>) -> Result { as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_slice()) } + fn dearbitrary(&self) -> Vec { + as Arbitrary>::dearbitrary(&self.to_vec()) + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { as Arbitrary>::size_hint(depth) @@ -929,6 +1135,10 @@ impl<'a> Arbitrary<'a> for Box { ::arbitrary(u).map(|x| x.into_boxed_str()) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) @@ -953,6 +1163,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Arc { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, ::size_hint) @@ -964,6 +1178,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Rc { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, ::size_hint) @@ -975,6 +1193,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Cell { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -986,6 +1208,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for RefCell { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -997,6 +1223,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for UnsafeCell { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -1008,6 +1238,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Mutex { Arbitrary::arbitrary(u).map(Self::new) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -1019,6 +1253,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for iter::Empty { Ok(iter::empty()) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) @@ -1030,6 +1268,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::marker::PhantomData { Ok(::std::marker::PhantomData) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) @@ -1041,6 +1283,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::num::Wrapping { Arbitrary::arbitrary(u).map(::std::num::Wrapping) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -1057,6 +1303,10 @@ macro_rules! implement_nonzero_int { } } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { <$int as Arbitrary<'a>>::size_hint(depth) @@ -1083,6 +1333,10 @@ impl<'a> Arbitrary<'a> for Ipv4Addr { Ok(Ipv4Addr::from(u32::arbitrary(u)?)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (4, Some(4)) @@ -1094,6 +1348,10 @@ impl<'a> Arbitrary<'a> for Ipv6Addr { Ok(Ipv6Addr::from(u128::arbitrary(u)?)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (16, Some(16)) @@ -1126,6 +1384,31 @@ mod test { assert_eq!(expected, actual); } + #[test] + fn dearbitrary_for_integers() { + let x = 1 | (2 << 8) | (3 << 16) | (4 << 24); + let expected = vec![1, 2, 3, 4]; + let actual = i32::dearbitrary(&x); + assert_eq!(expected, actual); + + let x = 1 | (2 << 8) | (3 << 16) | (4 << 24) | (5 << 32) | (6 << 40) | (7 << 48) | (8 << 56); + let expected = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let actual = i64::dearbitrary(&x); + assert_eq!(expected, actual); + + let expected = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let mut buf = Unstructured::new(&expected); + let x = i64::arbitrary(&mut buf).unwrap(); + let actual = i64::dearbitrary(&x); + assert_eq!(expected, actual); + + let expected = vec![1, 2, 3, 4]; + let mut buf = Unstructured::new(&expected); + let x = u32::arbitrary(&mut buf).unwrap(); + let actual = u32::dearbitrary(&x); + assert_eq!(expected, actual); + } + #[test] fn arbitrary_for_bytes() { let x = [1, 2, 3, 4, 4]; @@ -1135,6 +1418,14 @@ mod test { assert_eq!(expected, actual); } + #[test] + fn dearbitrary_for_bytes() { + let x = &[1u8, 2u8, 3u8, 4u8]; + let expected = [1, 2, 3, 4, 4]; + let actual = <&[u8] as Arbitrary>::dearbitrary(&x.as_slice()); + assert_eq!(expected.as_slice(), actual); + } + #[test] fn arbitrary_take_rest_for_bytes() { let x = [1, 2, 3, 4]; @@ -1163,6 +1454,14 @@ mod test { ); } + #[test] + fn dearbitrary_collection() { + let x = vec![2, 4, 6, 8, 1]; + let expected = [1, 2, 1, 4, 1, 6, 1, 8, 1, 1, 0]; + let actual = Vec::::dearbitrary(&x); + assert_eq!(expected.as_slice(), actual); + } + #[test] fn arbitrary_take_rest() { let x = [1, 2, 3, 4]; @@ -1191,4 +1490,37 @@ mod test { <(u8, Vec) as Arbitrary>::size_hint(0) ); } + + #[test] + fn dearbitrary_tuples() { + let x = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8]; + let mut buf = Unstructured::new(&x); + let t = <(u16,u32,u8,u8,u8,u8)>::arbitrary(&mut buf).unwrap(); + let actual = Arbitrary::dearbitrary(&t); + + assert_eq!(x.to_vec(), actual); + + let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let mut buf = Unstructured::new(&x); + let t = <(bool, bool, u32,u8,u8,u8,u8)>::arbitrary(&mut buf).unwrap(); + let actual = Arbitrary::dearbitrary(&t); + + assert_eq!(x.to_vec(), actual); + + + let x = [1, 0, 3, 4, 5, 0, 7, 8, 9, 0]; + let mut buf = Unstructured::new(&x); + let t = <(u32, u8, bool,u8,u8,u8,u8)>::arbitrary(&mut buf).unwrap(); + let actual = Arbitrary::dearbitrary(&t); + + assert_eq!(x.to_vec(), actual); + + let x = (true, 2); + let data = [1, 2, 0, 0, 0, 0, 0, 0, 0]; + let actual = <(bool, u64)>::dearbitrary(&x); + assert_eq!(data.to_vec(), actual); + let mut buf = Unstructured::new(&data); + let expected = <(bool, u64)>::arbitrary(&mut buf).unwrap(); + assert_eq!(expected, x); + } } diff --git a/src/unstructured.rs b/src/unstructured.rs index ad3ffc0..31f4f01 100644 --- a/src/unstructured.rs +++ b/src/unstructured.rs @@ -207,6 +207,10 @@ impl<'a> Unstructured<'a> { /// /// Ok(my_collection) /// } + /// + /// fn dearbitrary(&self) -> Vec { + /// unimplemented!() + /// } /// } /// ``` pub fn arbitrary_len(&mut self) -> Result diff --git a/tests/derive.rs b/tests/derive.rs index 9dfbbd5..d1253ad 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -24,6 +24,14 @@ fn struct_with_named_fields() { assert_eq!((3, Some(3)), ::size_hint(0)); } +#[test] +fn dearbitrary_struct_with_named_fields() { + let rgb = Rgb { r: 4, g: 5, b: 6 }; + let expected = vec![4, 5, 6]; + let actual = Rgb::dearbitrary(&rgb); + assert_eq!(expected, actual); +} + #[derive(Copy, Clone, Debug, Arbitrary)] struct MyTupleStruct(u8, bool); @@ -60,13 +68,44 @@ fn test_take_rest() { assert_eq!(s2.3, "\x05\x06\x07\x08"); } -#[derive(Copy, Clone, Debug, Arbitrary)] +#[derive(Copy, Clone, Debug, Arbitrary, PartialEq)] enum MyEnum { Unit, Tuple(u8, u16), Struct { a: u32, b: (bool, u64) }, } +#[test] +fn dearbitrary_enum() { + let x = MyEnum::Unit; + let expected = vec![0, 0, 0, 0]; + let actual = MyEnum::dearbitrary(&x); + assert_eq!(actual, expected); + let mut buf = Unstructured::new(&expected); + let actual2 = MyEnum::arbitrary(&mut buf).unwrap(); + assert_eq!(actual2, x); + + let x = MyEnum::Tuple(1, 2); + let expected = vec![86, 85, 85, 85, 1, 2, 0]; + let actual = MyEnum::dearbitrary(&x); + assert_eq!(actual, expected); + + + let mut buf = Unstructured::new(&expected); + let actual2 = MyEnum::arbitrary(&mut buf).unwrap(); + assert_eq!(actual2, x); + + + let x = MyEnum::Struct { a: 157, b: (true, 1) }; + let expected = vec![171, 170, 170, 170, 157, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]; + let actual = MyEnum::dearbitrary(&x); + assert_eq!(actual, expected); + + let mut buf = Unstructured::new(&expected); + let actual2 = MyEnum::arbitrary(&mut buf).unwrap(); + assert_eq!(actual2, x); +} + #[test] fn derive_enum() { let mut raw = vec![