From 000e7c4e4c2e5aca557503403e7e9cea8da5fc80 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 15 Aug 2023 14:25:08 +0100 Subject: [PATCH 1/4] Improves the docs on derive So I've done a bit of work to improve the derive docs. I do think another improvement may be to copy the style done in the tokio docs and for some simple examples show how the generated code looks. However, I think fake would benefit less from this compared to tokio (how a runtime is setup for an async application is important to more people). So it may just add unnecessary noise to the docs. I guess an issue should be made for the tuple enums - or maybe there's another way to do it I need to experiment/read-macro-code more --- fake/src/lib.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/fake/src/lib.rs b/fake/src/lib.rs index e16ef6f..9aa3ec9 100644 --- a/fake/src/lib.rs +++ b/fake/src/lib.rs @@ -271,10 +271,15 @@ pub mod faker; /// Locales used for custom [`Dummy`] implementations within [`faker`] module. pub mod locales; -/// Derive macro generating an impl of the trait [`Dummy`]. +/// Derive macro generating an impl of the trait [`Dummy`]. This works for both structs and enums. +/// +/// For any fields in the type the `faker` key in `dummy` attribute could be used provided the field +/// implements [`Fake`]. /// /// # Examples /// +/// A simple example for deriving [`Dummy`] on a struct: +/// /// ``` /// use fake::{Dummy, Fake, Faker}; /// use fake::faker::name::en::Name; @@ -291,8 +296,26 @@ pub mod locales; /// let f: Foo = Faker.fake(); /// ``` /// -/// `faker` key in `dummy` attribute could be used on any type that implements -/// [`Fake`]. +/// A simple example for deriving [`Dummy`] on an enum. Unfortunately, the `faker` key cannot yet +/// be used on tuple enum variants. However, it can be used on fields within struct enum variants. +/// +/// ``` +/// use fake::{Dummy, Fake, Faker}; +/// use fake::faker::name::en::Name; +/// +/// #[derive(Dummy)] +/// pub struct Bar { +/// Simple, +/// Tuple(i32), +/// Structure { +/// #[dummy(faker = "1000..2000")] +/// i: usize, +/// j: String, +/// } +/// } +/// +/// let f: Foo = Faker.fake(); +/// ``` #[cfg(feature = "derive")] pub use dummy::Dummy; From d68c032aabef71e7b0842f04284e37cd0cc05078 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 15 Aug 2023 14:29:23 +0100 Subject: [PATCH 2/4] Correct docs on tuple enums --- fake/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fake/src/lib.rs b/fake/src/lib.rs index 9aa3ec9..1172c9f 100644 --- a/fake/src/lib.rs +++ b/fake/src/lib.rs @@ -296,17 +296,18 @@ pub mod locales; /// let f: Foo = Faker.fake(); /// ``` /// -/// A simple example for deriving [`Dummy`] on an enum. Unfortunately, the `faker` key cannot yet -/// be used on tuple enum variants. However, it can be used on fields within struct enum variants. +/// A simple example for deriving [`Dummy`] on an enum. For enum tuple variants the faker attribute +/// is applied directly to the types in the tuple, for struct variants it is applied on each struct +/// field. /// /// ``` /// use fake::{Dummy, Fake, Faker}; /// use fake::faker::name::en::Name; /// /// #[derive(Dummy)] -/// pub struct Bar { +/// pub enum Bar { /// Simple, -/// Tuple(i32), +/// Tuple(#[dummy(faker="0..5")] i32), /// Structure { /// #[dummy(faker = "1000..2000")] /// i: usize, @@ -314,7 +315,7 @@ pub mod locales; /// } /// } /// -/// let f: Foo = Faker.fake(); +/// let b: Bar = Faker.fake(); /// ``` #[cfg(feature = "derive")] pub use dummy::Dummy; From 36713c1a2969604cb8de1d60d965482eff315df3 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 15 Aug 2023 17:24:57 +0100 Subject: [PATCH 3/4] Apply PR feedback --- fake/src/lib.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/fake/src/lib.rs b/fake/src/lib.rs index 1172c9f..62a33e8 100644 --- a/fake/src/lib.rs +++ b/fake/src/lib.rs @@ -64,6 +64,12 @@ //! let v: usize = Faker.fake_with_rng(r); //! println!("value from fixed seed {}", v); //! } +//! +//! // Use an always true RNG so that optional types are always `Some` values. +//! use fake::utils::AlwaysTrueRng; +//! let mut rng = AlwaysTrueRng::default(); +//! let result: Option = Faker.fake_with_rng(&mut rng); +//! println!("Always Some: {}", result.unwrap()); //! ``` use rand::Rng; @@ -273,8 +279,14 @@ pub mod locales; /// Derive macro generating an impl of the trait [`Dummy`]. This works for both structs and enums. /// -/// For any fields in the type the `faker` key in `dummy` attribute could be used provided the field -/// implements [`Fake`]. +/// # Attributes +/// +/// For any fields in the type there are a number of keys that can be used to control the code generation. +/// All of these go within the dummy attribute. +/// +/// 1. `faker` key can be used to provide a specific faker for a field provided it implements [`Fake`]. +/// 2. `expr` key can be used to provide a rust expression as a fixed value. +/// 3. `default` key sets the value to the types [`Default`] implementation. /// /// # Examples /// @@ -291,6 +303,45 @@ pub mod locales; /// #[dummy(faker = "Name()")] /// customer: String, /// paid: bool, +/// #[dummy(expr = "\"Fixed\".into()")] +/// fixed_value: String, +/// #[dummy(default)] +/// other: String, +/// } +/// +/// let f: Foo = Faker.fake(); +/// ``` +/// +/// This would generate code roughly equivalent to: +/// +/// ``` +/// use fake::{Dummy, Fake, Faker}; +/// use fake::faker::name::en::Name; +/// use rand::Rng; +/// +/// pub struct Foo { +/// order_id: usize, +/// customer: String, +/// paid: bool, +/// fixed_value: String, +/// other: String, +/// } +/// +/// impl Dummy for Foo { +/// fn dummy_with_rng(_: &Faker, rng: &mut R) -> Self { +/// let order_id = Fake::fake_with_rng::(&(1000..2000), rng); +/// let customer = Fake::fake_with_rng::(&(Name()), rng); +/// let paid = Fake::fake_with_rng::(&Faker, rng); +/// let fixed_value = "Fixed".into(); +/// let other = Default::default(); +/// Self { +/// order_id, +/// customer, +/// paid, +/// fixed_value, +/// other, +/// } +/// } /// } /// /// let f: Foo = Faker.fake(); @@ -317,6 +368,40 @@ pub mod locales; /// /// let b: Bar = Faker.fake(); /// ``` +/// +/// This will generate code roughly equivalent to: +/// +/// ``` +/// use fake::{Dummy, Fake, Faker}; +/// use fake::faker::name::en::Name; +/// use rand::Rng; +/// +/// pub enum Bar { +/// Simple, +/// Tuple(i32), +/// Structure { +/// i: usize, +/// j: String, +/// } +/// } +/// +/// impl Dummy for Bar { +/// fn dummy_with_rng(_: &Faker, rng: &mut R) -> Self { +/// match rng.gen_range(0..3usize) { +/// 0 => Self::Simple, +/// 1 => Self::Tuple(Fake::fake_with_rng::(&(0..5), rng)), +/// 2 => { +/// let i = Fake::fake_with_rng::(&(1000..2000), rng); +/// let j = Fake::fake_with_rng::(&Faker, rng); +/// Self::Structure { i, j } +/// }, +/// _ => unreachable!(), +/// } +/// } +/// } +/// +/// let b: Bar = Faker.fake(); +/// ``` #[cfg(feature = "derive")] pub use dummy::Dummy; From 639f92bac3fac202c1e6a3c6a0367292b220500d Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 15 Aug 2023 17:49:41 +0100 Subject: [PATCH 4/4] Add in config tuple --- fake/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fake/src/lib.rs b/fake/src/lib.rs index 62a33e8..d439925 100644 --- a/fake/src/lib.rs +++ b/fake/src/lib.rs @@ -50,6 +50,12 @@ //! let words: Vec = Words(3..5).fake(); //! println!("words {:?}", words); //! +//! // Using a tuple config list to generate a vector with a length range and a specific faker for the element +//! let name_vec: Vec = (Name(EN), 3..5).fake(); +//! +//! // Using a macro as an alternative method for the tuple config list +//! let name_vec = fake::vec![String as Name(EN); 3..5]; +//! //! // using macro to generate nested collection //! let name_vec = fake::vec![String as Name(EN); 4, 3..5, 2]; //! println!("random nested vec {:?}", name_vec); @@ -65,7 +71,8 @@ //! println!("value from fixed seed {}", v); //! } //! -//! // Use an always true RNG so that optional types are always `Some` values. +//! // Use an always true RNG so that optional types are always `Some` values. (Requires +//! // always-true-rng feature). //! use fake::utils::AlwaysTrueRng; //! let mut rng = AlwaysTrueRng::default(); //! let result: Option = Faker.fake_with_rng(&mut rng);