From dd34c0625f3b1ec4824803b91cb729d6326a46f3 Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:29:04 +0100 Subject: [PATCH 1/7] added preliminary support for revert mode # Conflicts: # src/lib.rs --- derive/src/lib.rs | 98 ++++++++++++++++++ src/lib.rs | 246 +++++++++++++++++++++++++++++++++++++++++++- src/unstructured.rs | 4 + tests/derive.rs | 8 ++ 4 files changed, 355 insertions(+), 1 deletion(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 983bd68..6867ecd 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,102 @@ 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)) + } + }); + //let dearbitrary_take_rest = construct_take_rest(fields); + 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 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(); + //x = (u64(xu32) * #count) >> 32 + + let val = match self { + #(#variants,)* + _ => unreachable!() + }; + let x = ((val << 32) / #count ) as u32; + v.append(&mut x.to_le_bytes().to_vec()); + v.append(&mut arbitrary::Arbitrary::dearbitrary(self)); + v + } + } + } + } +} + +fn cons(fields: &Fields) -> 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! { #name } + }); + quote! { { #(#names,)* } } + } + Fields::Unnamed(names) => { + let names = names.unnamed.iter().enumerate().map(|(i, f)| { + quote! { _ } + }); + 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..29a3016 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,10 @@ pub trait Arbitrary<'a>: Sized { /// See also the documentation for [`Unstructured`][crate::Unstructured]. fn arbitrary(u: &mut Unstructured<'a>) -> Result; + + /// reverts the progress of Arbitrary::arbitrary + 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 +242,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 +279,10 @@ impl<'a> Arbitrary<'a> for () { Ok(()) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) @@ -278,6 +294,14 @@ impl<'a> Arbitrary<'a> for bool { Ok(>::arbitrary(u)? & 1 == 1) } + fn dearbitrary(&self) -> Vec { + if *self { + vec![1] + } else { + vec![0] + } + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -298,6 +322,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 +364,10 @@ macro_rules! impl_arbitrary_for_floats { Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { <$unsigned as Arbitrary<'a>>::size_hint(depth) @@ -364,6 +400,10 @@ impl<'a> Arbitrary<'a> for char { } } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) @@ -375,6 +415,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 +430,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 +445,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 +472,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 +555,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 +577,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 +599,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( @@ -557,6 +625,10 @@ macro_rules! arbitrary_tuple { Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[allow(unused_mut, non_snake_case)] fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { $(let $xs = $xs::arbitrary(&mut u)?;)* @@ -644,6 +716,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 +743,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().clone()); + v.append(&mut len_bytes); + v + } + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { Ok(u.take_rest()) } @@ -682,6 +779,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 +804,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 +823,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 +842,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 +863,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 +884,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 +903,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 +922,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 +945,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 +977,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 +999,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 +1021,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 +1036,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 +1051,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 +1063,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] @@ -918,6 +1082,10 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<[A]> { as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_slice()) } + fn dearbitrary(&self) -> Vec { + unimplemented!() + } + #[inline] fn size_hint(depth: usize) -> (usize, Option) { as Arbitrary>::size_hint(depth) @@ -929,6 +1097,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 +1125,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 +1140,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 +1155,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 +1170,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 +1185,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 +1200,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 +1215,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 +1230,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 +1245,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 +1265,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 +1295,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 +1310,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 +1346,14 @@ 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); + } + #[test] fn arbitrary_for_bytes() { let x = [1, 2, 3, 4, 4]; @@ -1135,6 +1363,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 +1399,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]; 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..4e161c9 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); From ca48fc1a63b5ee1f2157be4625840f9a43159e99 Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:29:36 +0100 Subject: [PATCH 2/7] fixes for Box<[A]> # Conflicts: # src/lib.rs --- src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 29a3016..2b7d8cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1077,13 +1077,16 @@ 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 { - unimplemented!() + // for x in self.iter() { + // v.push(*x.clone()); + // } + as Arbitrary>::dearbitrary(&self.to_vec()) } #[inline] From 5e096d193e2e0b6b4d7acf4a38dee70d8cf45d59 Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:30:18 +0100 Subject: [PATCH 3/7] added working derive # Conflicts: # src/lib.rs --- derive/src/lib.rs | 51 ++++++++++++++++++++--- src/lib.rs | 103 +++++++++++++++++++++++++++++++++++++++++----- tests/derive.rs | 33 ++++++++++++++- 3 files changed, 170 insertions(+), 17 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 6867ecd..22d621e 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -101,6 +101,15 @@ fn gen_dearbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenSt 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 { @@ -108,15 +117,21 @@ fn gen_dearbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenSt // with slight bias. For details, see: // https://lemire.me/blog/2016/06/30/fast-random-shuffling let mut v = Vec::new(); - //x = (u64(xu32) * #count) >> 32 - let val = match self { #(#variants,)* _ => unreachable!() }; - let x = ((val << 32) / #count ) as u32; - v.append(&mut x.to_le_bytes().to_vec()); - v.append(&mut arbitrary::Arbitrary::dearbitrary(self)); + 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 } } @@ -124,6 +139,29 @@ fn gen_dearbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenSt } } +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(); + //let ctor = ctor(i, f); + 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) => { @@ -136,7 +174,8 @@ fn cons(fields: &Fields) -> TokenStream { } Fields::Unnamed(names) => { let names = names.unnamed.iter().enumerate().map(|(i, f)| { - quote! { _ } + let id = Ident::new(&format!("x{}", i), Span::call_site());; + quote! { #id } }); quote! { ( #(#names),* ) } } diff --git a/src/lib.rs b/src/lib.rs index 2b7d8cb..1a01478 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -296,9 +296,9 @@ impl<'a> Arbitrary<'a> for bool { fn dearbitrary(&self) -> Vec { if *self { - vec![1] + u8::dearbitrary(&1) } else { - vec![0] + u8::dearbitrary(&0) } } @@ -325,7 +325,7 @@ macro_rules! impl_arbitrary_for_integers { 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[i] = ((*self as $unsigned >> (i * 8)) & 0xFF ) as u8; } buf.to_vec() } @@ -615,10 +615,16 @@ 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 { @@ -626,7 +632,11 @@ macro_rules! arbitrary_tuple { } fn dearbitrary(&self) -> Vec { - unimplemented!() + 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)] @@ -646,7 +656,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. @@ -1083,9 +1119,6 @@ impl<'a, A: Arbitrary<'a> + Clone> Arbitrary<'a> for Box<[A]> { } fn dearbitrary(&self) -> Vec { - // for x in self.iter() { - // v.push(*x.clone()); - // } as Arbitrary>::dearbitrary(&self.to_vec()) } @@ -1355,6 +1388,23 @@ mod test { 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] @@ -1438,4 +1488,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/tests/derive.rs b/tests/derive.rs index 4e161c9..d1253ad 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -68,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![ From a87179c96791ad20b4e1fdac4deed681ef774f5a Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:34:12 +0100 Subject: [PATCH 4/7] small cleanups --- derive/src/lib.rs | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 22d621e..0ef351f 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -165,7 +165,7 @@ fn cons2(fields: &Fields) -> TokenStream { fn cons(fields: &Fields) -> TokenStream { match fields { Fields::Named(names) => { - let names = names.named.iter().enumerate().map(|(i, f)| { + let names = names.named.iter().enumerate().map(|(_, f)| { let name = f.ident.as_ref().unwrap(); //let ctor = ctor(i, f); quote! { #name } @@ -173,7 +173,7 @@ fn cons(fields: &Fields) -> TokenStream { quote! { { #(#names,)* } } } Fields::Unnamed(names) => { - let names = names.unnamed.iter().enumerate().map(|(i, f)| { + let names = names.unnamed.iter().enumerate().map(|(i, _)| { let id = Ident::new(&format!("x{}", i), Span::call_site());; quote! { #id } }); diff --git a/src/lib.rs b/src/lib.rs index 1a01478..f48ffe4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -795,7 +795,7 @@ impl<'a> Arbitrary<'a> for &'a [u8] { }; let mut v = Vec::new(); - v.append(&mut self.to_vec().clone()); + v.append(&mut self.to_vec()); v.append(&mut len_bytes); v } From 4fa1fbcb0db457e66661c402a8397283e420241a Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:38:20 +0100 Subject: [PATCH 5/7] remove code --- derive/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 0ef351f..3d826b9 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -81,7 +81,6 @@ fn gen_dearbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenSt quote!(arbitrary::Arbitrary::dearbitrary(&self.#a)) } }); - //let dearbitrary_take_rest = construct_take_rest(fields); quote! { fn dearbitrary(&self) -> Vec { let mut v: Vec = Vec::new(); @@ -144,7 +143,6 @@ fn cons2(fields: &Fields) -> TokenStream { 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 arbitrary::Arbitrary::dearbitrary(#name))) }); @@ -167,7 +165,6 @@ fn cons(fields: &Fields) -> TokenStream { Fields::Named(names) => { let names = names.named.iter().enumerate().map(|(_, f)| { let name = f.ident.as_ref().unwrap(); - //let ctor = ctor(i, f); quote! { #name } }); quote! { { #(#names,)* } } From 25283edbf30f37a0d4b93457472861a9112fc831 Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:38:37 +0100 Subject: [PATCH 6/7] added some doc --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f48ffe4..181face 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -179,7 +179,9 @@ pub trait Arbitrary<'a>: Sized { fn arbitrary(u: &mut Unstructured<'a>) -> Result; - /// reverts the progress of Arbitrary::arbitrary + /// 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. From 2b87ed56a1daf3e07f949caea3e0dcca5c5d6423 Mon Sep 17 00:00:00 2001 From: bitwave Date: Sat, 25 Dec 2021 14:49:03 +0100 Subject: [PATCH 7/7] added more impls --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 181face..1a6b98c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -282,7 +282,7 @@ impl<'a> Arbitrary<'a> for () { } fn dearbitrary(&self) -> Vec { - unimplemented!() + Vec::new() } #[inline] @@ -367,7 +367,7 @@ macro_rules! impl_arbitrary_for_floats { } fn dearbitrary(&self) -> Vec { - unimplemented!() + <$unsigned>::dearbitrary(&Self::to_bits(*self)) } #[inline] @@ -403,7 +403,7 @@ impl<'a> Arbitrary<'a> for char { } fn dearbitrary(&self) -> Vec { - unimplemented!() + u32::dearbitrary(&(*self as u32)) } #[inline]