//-
// Copyright 2017, 2018 The proptest developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use fmt;
use crate Strategy;
//==============================================================================
// Arbitrary trait
//==============================================================================
/// Arbitrary determines a canonical [`Strategy`] for the implementing type.
///
/// It provides the method `arbitrary_with` which generates a `Strategy` for
/// producing arbitrary values of the implementing type *(`Self`)*. In general,
/// these strategies will produce the entire set of values possible for the
/// type, up to some size limitation or constraints set by their parameters.
/// When this is not desired, strategies to produce the desired values can be
/// built by combining [`Strategy`]s as described in the crate documentation.
///
/// This trait analogous to
/// [Haskell QuickCheck's implementation of `Arbitrary`][HaskellQC].
/// In this interpretation of `Arbitrary`, `Strategy` is the equivalent of
/// the `Gen` monad. Unlike in QuickCheck, `Arbitrary` is not a core component;
/// types do not need to implement `Arbitrary` unless one wants to use
/// [`any`](fn.any.html) or other free functions in this module.
///
/// `Arbitrary` currently only works for types which represent owned data as
/// opposed to borrowed data. This is a fundamental restriction of `proptest`
/// which may be lifted in the future as the [generic associated types (GAT)]
/// feature of Rust is implemented and stabilized.
///
/// [generic associated types (GAT)]: https://github.com/rust-lang/rust/issues/44265
///
/// [`Strategy`]: ../strategy/trait.Strategy.html
///
/// [HaskellQC]:
/// https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
//==============================================================================
// Type aliases for associated types
//==============================================================================
/// `StrategyFor` allows you to mention the type of [`Strategy`] for the input
/// type `A` without directly using associated types or without resorting to
/// existential types. This way, if implementation of [`Arbitrary`] changes,
/// your tests should not break. This can be especially beneficial when the
/// type of `Strategy` that you are dealing with is very long in name
/// (the case with generics).
///
/// [`Arbitrary`]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html
pub type StrategyFor<A> = Strategy;
/// `ParamsFor` allows you to mention the type of [`Parameters`] for the input
/// type `A` without directly using associated types or without resorting to
/// existential types. This way, if implementation of [`Arbitrary`] changes,
/// your tests should not break.
///
/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
/// [`Arbitrary`]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html
pub type ParamsFor<A> = Parameters;
//==============================================================================
// Free functions that people should use
//==============================================================================
/// Generates a [`Strategy`] producing [`Arbitrary`][trait Arbitrary] values of
/// `A`. Unlike [`arbitrary`][fn arbitrary], it should be used for being
/// explicit on what `A` is. For clarity, this may be a good idea.
///
/// Use this version instead of [`arbitrary`][fn arbitrary] if you want to be
/// clear which type you want to generate a `Strategy` for, or if you don't
/// have an anchoring type for type inference to work with.
///
/// If you want to customize how the strategy is generated, use
/// [`any_with::<A>(args)`] where `args` are any arguments accepted by
/// the `Arbitrary` impl in question.
///
/// # Example
///
/// The function can be used as:
///
/// ```rust
/// use proptest::prelude::*;
///
/// proptest! {
/// fn reverse_reverse_is_identity(ref vec in any::<Vec<u32>>()) {
/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
/// prop_assert_eq!(vec, &vec2);
/// }
/// }
///
/// fn main() {
/// reverse_reverse_is_identity();
/// }
/// ```
///
/// [`any_with::<A>(args)`]: fn.any_with.html
/// [fn arbitrary]: fn.arbitrary.html
/// [trait Arbitrary]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html
/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
/// given configuration arguments passed in `args`. Unlike [`arbitrary_with`],
/// it should be used for being explicit on what `A` is.
/// For clarity, this may be a good idea.
///
/// Use this version instead of [`arbitrary_with`] if you want to be clear which
/// type you want to generate a `Strategy` for, or if you don't have an anchoring
/// type for type inference to work with.
///
/// If you don't want to specify any arguments and instead use the default
/// behavior, you should use [`any::<A>()`].
///
/// # Example
///
/// The function can be used as:
///
/// ```rust
/// use proptest::prelude::*;
/// use proptest::collection::size_range;
///
/// proptest! {
/// fn reverse_reverse_is_identity
/// (ref vec in any_with::<Vec<u32>>(size_range(1000).lift()))
/// {
/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
/// prop_assert_eq!(vec, &vec2);
/// }
/// }
///
/// fn main() {
/// reverse_reverse_is_identity();
/// }
/// ```
///
/// [`any::<A>()`]: fn.any.html
/// [`arbitrary_with`]: fn.arbitrary_with.html
/// [`Arbitrary`]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html
/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
/// Works better with type inference than [`any::<A>()`].
///
/// With this version, you shouldn't need to specify any of the (many) type
/// parameters explicitly. This can have a positive effect on type inference.
/// However, if you want specify `A`, you should use [`any::<A>()`] instead.
///
/// For clarity, it is often a good idea to specify the type generated, and
/// so using [`any::<A>()`] can be a good idea.
///
/// If you want to customize how the strategy is generated, use
/// [`arbitrary_with(args)`] where `args` is of type
/// `<A as Arbitrary>::Parameters`.
///
/// # Example
///
/// The function can be used as:
///
/// ```rust
/// extern crate proptest;
/// use proptest::arbitrary::{arbitrary, StrategyFor};
///
/// fn gen_vec_usize() -> StrategyFor<Vec<usize>> {
/// arbitrary()
/// }
///
/// # fn main() {}
/// ```
///
/// [`arbitrary_with(args)`]: fn.arbitrary_with.html
/// [`any::<A>()`]: fn.any.html
/// [`Arbitrary`]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html
/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
/// given configuration arguments passed in `args`.
/// Works better with type inference than [`any_with::<A>(args)`].
///
/// With this version, you shouldn't need to specify any of the (many) type
/// parameters explicitly. This can have a positive effect on type inference.
/// However, if you want specify `A`, you should use
/// [`any_with::<A>(args)`] instead.
///
/// For clarity, it is often a good idea to specify the type generated, and
/// so using [`any_with::<A>(args)`] can be a good idea.
///
/// If you don't want to specify any arguments and instead use the default
/// behavior, you should use [`arbitrary()`].
///
/// # Example
///
/// The function can be used as:
///
/// ```rust
/// extern crate proptest;
/// use proptest::arbitrary::{arbitrary_with, StrategyFor};
/// use proptest::collection::size_range;
///
/// fn gen_vec_10_u32() -> StrategyFor<Vec<u32>> {
/// arbitrary_with(size_range(10).lift())
/// }
///
/// # fn main() {}
/// ```
///
/// [`any_with::<A>(args)`]: fn.any_with.html
/// [`arbitrary()`]: fn.arbitrary.html
/// [`Arbitrary`]: trait.Arbitrary.html
/// [`Strategy`]: ../strategy/trait.Strategy.html