Struct contrafact::Generator

source ·
pub struct Generator<'a> { /* private fields */ }
Expand description

Generators are used to generate new values and error messages.

For mutation logic which actually generates new data, error messages are produced instead of data during a Check. In some cases, Generator::fail must be used when attempting to mutate data using existing values not generated by Generator.

Implementations§

source§

impl<'a> Generator<'a>

source

pub fn fail(&self, err: impl ToString) -> Mutation<()>

When running a Check, fail immediately with this error. This should be used in cases where a mutation occurs using some known value, rather than generating a value from the Generator itself.

source

pub fn set<T: PartialEq + Clone, S: ToString>( &self, source: &mut T, target: &T, err: impl FnOnce() -> S ) -> Mutation<()>

When running a Check, fail immediately with this error if the existing value doesn’t match. During mutation, set the value so that it does match.

source

pub fn arbitrary<T: Arbitrary<'a>, S: ToString>( &mut self, err: impl FnOnce() -> S ) -> Mutation<T>

Generate arbitrary data in mutation mode, or produce an error in check mode

source

pub fn choose<T: Arbitrary<'a>, S: ToString>( &mut self, choices: &'a [T], err: impl FnOnce() -> S ) -> Mutation<&T>

Choose between specified items in mutation mode, or produce an error in check mode.

source

pub fn int_in_range<T, S>( &mut self, range: RangeInclusive<T>, err: impl FnOnce() -> S ) -> Mutation<T>where T: Arbitrary<'a> + PartialOrd + Copy + Int, S: ToString,

Exposes int_in_range from underlying Unstructured in mutation mode, or produce an error in check mode. Note that even though arbitrary says NOT to use this for calculating the size of a collection to build, that’s exactly what I will be doing with this, because I’m not sure exactly what the contrafact story is for size hints (which is what arbitrary would be using instead).

source

pub fn with<T, S: ToString>( &mut self, err: impl FnOnce() -> S, f: impl FnOnce(&mut Unstructured<'a>) -> Result<T, Error> ) -> Mutation<T>

Call the specified Arbitrary function in mutation mode, or produce an error in check mode.

Methods from Deref<Target = Unstructured<'a>>§

source

pub fn len(&self) -> usize

Get the number of remaining bytes of underlying data that are still available.

Example
use arbitrary::{Arbitrary, Unstructured};

let mut u = Unstructured::new(&[1, 2, 3]);

// Initially have three bytes of data.
assert_eq!(u.len(), 3);

// Generating a `bool` consumes one byte from the underlying data, so
// we are left with two bytes afterwards.
let _ = bool::arbitrary(&mut u);
assert_eq!(u.len(), 2);
source

pub fn is_empty(&self) -> bool

Is the underlying unstructured data exhausted?

unstructured.is_empty() is the same as unstructured.len() == 0.

Example
use arbitrary::{Arbitrary, Unstructured};

let mut u = Unstructured::new(&[1, 2, 3, 4]);

// Initially, we are not empty.
assert!(!u.is_empty());

// Generating a `u32` consumes all four bytes of the underlying data, so
// we become empty afterwards.
let _ = u32::arbitrary(&mut u);
assert!(u.is_empty());
source

pub fn arbitrary<A>(&mut self) -> Result<A, Error>where A: Arbitrary<'a>,

Generate an arbitrary instance of A.

This is simply a helper method that is equivalent to <A as Arbitrary>::arbitrary(self). This helper is a little bit more concise, and can be used in situations where Rust’s type inference will figure out what A should be.

Example
use arbitrary::{Arbitrary, Unstructured};

#[derive(Arbitrary)]
struct MyType {
    // ...
}

fn do_stuff(value: MyType) {
    // ...
}

let mut u = Unstructured::new(&[1, 2, 3, 4]);

// Rust's type inference can figure out that `value` should be of type
// `MyType` here:
let value = u.arbitrary()?;
do_stuff(value);
source

pub fn arbitrary_len<ElementType>(&mut self) -> Result<usize, Error>where ElementType: Arbitrary<'a>,

Get the number of elements to insert when building up a collection of arbitrary ElementTypes.

This uses the <ElementType as Arbitrary>::size_hint method to smartly choose a length such that we most likely have enough underlying bytes to construct that many arbitrary ElementTypes.

This should only be called within an Arbitrary implementation.

Example
use arbitrary::{Arbitrary, Result, Unstructured};

impl<'a, T> Arbitrary<'a> for MyCollection<T>
where
    T: Arbitrary<'a>,
{
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
        // Get the number of `T`s we should insert into our collection.
        let len = u.arbitrary_len::<T>()?;

        // And then create a collection of that length!
        let mut my_collection = MyCollection::with_capacity(len);
        for _ in 0..len {
            let element = T::arbitrary(u)?;
            my_collection.insert(element);
        }

        Ok(my_collection)
    }
}
source

pub fn int_in_range<T>(&mut self, range: RangeInclusive<T>) -> Result<T, Error>where T: Int,

Generate an integer within the given range.

Do not use this to generate the size of a collection. Use arbitrary_len instead.

Panics

Panics if range.start > range.end. That is, the given range must be non-empty.

Example
use arbitrary::{Arbitrary, Unstructured};

let mut u = Unstructured::new(&[1, 2, 3, 4]);

let x: i32 = u.int_in_range(-5_000..=-1_000)
    .expect("constructed `u` with enough bytes to generate an `i32`");

assert!(-5_000 <= x);
assert!(x <= -1_000);
source

pub fn choose<T, 'b>(&mut self, choices: &'b [T]) -> Result<&'b T, Error>

Choose one of the given choices.

This should only be used inside of Arbitrary implementations.

Returns an error if there is not enough underlying data to make a choice or if no choices are provided.

Examples

Selecting from an array of choices:

use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
let choices = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

let choice = u.choose(&choices).unwrap();

println!("chose {}", choice);

An error is returned if no choices are provided:

use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
let choices: [char; 0] = [];

let result = u.choose(&choices);

assert!(result.is_err());
source

pub fn choose_index(&mut self, len: usize) -> Result<usize, Error>

Choose a value in 0..len.

Returns an error if the len is zero.

Examples

Using Fisher–Yates shuffle shuffle to gerate an arbitrary permutation.

use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
let mut permutation = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let mut to_permute = &mut permutation[..];
while to_permute.len() > 1 {
    let idx = u.choose_index(to_permute.len()).unwrap();
    to_permute.swap(0, idx);
    to_permute = &mut to_permute[1..];
}

println!("permutation: {:?}", permutation);

An error is returned if the length is zero:

use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
let array: [i32; 0] = [];

let result = u.choose_index(array.len());

assert!(result.is_err());
source

pub fn ratio<T>(&mut self, numerator: T, denominator: T) -> Result<bool, Error>where T: Int,

Generate a boolean according to the given ratio.

Panics

Panics when the numerator and denominator do not meet these constraints:

  • 0 < numerator <= denominator
Example

Generate a boolean that is true five sevenths of the time:

use arbitrary::Unstructured;

let mut u = Unstructured::new(&my_data);

if u.ratio(5, 7)? {
    // Take this branch 5/7 of the time.
}
source

pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error>

Fill a buffer with bytes from the underlying raw data.

This should only be called within an Arbitrary implementation. This is a very low-level operation. You should generally prefer calling nested Arbitrary implementations like <Vec<u8>>::arbitrary and String::arbitrary over using this method directly.

If this Unstructured does not have enough underlying data to fill the whole buffer, it pads the buffer out with zeros.

Example
use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4]);

let mut buf = [0; 2];

assert!(u.fill_buffer(&mut buf).is_ok());
assert_eq!(buf, [1, 2]);

assert!(u.fill_buffer(&mut buf).is_ok());
assert_eq!(buf, [3, 4]);

assert!(u.fill_buffer(&mut buf).is_ok());
assert_eq!(buf, [0, 0]);
source

pub fn bytes(&mut self, size: usize) -> Result<&'a [u8], Error>

Provide size bytes from the underlying raw data.

This should only be called within an Arbitrary implementation. This is a very low-level operation. You should generally prefer calling nested Arbitrary implementations like <Vec<u8>>::arbitrary and String::arbitrary over using this method directly.

Example
use arbitrary::Unstructured;

let mut u = Unstructured::new(&[1, 2, 3, 4]);

assert!(u.bytes(2).unwrap() == &[1, 2]);
assert!(u.bytes(2).unwrap() == &[3, 4]);
source

pub fn peek_bytes(&self, size: usize) -> Option<&'a [u8]>

Peek at size number of bytes of the underlying raw input.

Does not consume the bytes, only peeks at them.

Returns None if there are not size bytes left in the underlying raw input.

Example
use arbitrary::Unstructured;

let u = Unstructured::new(&[1, 2, 3]);

assert_eq!(u.peek_bytes(0).unwrap(), []);
assert_eq!(u.peek_bytes(1).unwrap(), [1]);
assert_eq!(u.peek_bytes(2).unwrap(), [1, 2]);
assert_eq!(u.peek_bytes(3).unwrap(), [1, 2, 3]);

assert!(u.peek_bytes(4).is_none());
source

pub fn arbitrary_iter<ElementType, 'b>( &'b mut self ) -> Result<ArbitraryIter<'a, 'b, ElementType>, Error>where ElementType: Arbitrary<'a>,

Provide an iterator over elements for constructing a collection

This is useful for implementing Arbitrary::arbitrary on collections since the implementation is simply u.arbitrary_iter()?.collect()

source

pub fn arbitrary_loop( &mut self, min: Option<u32>, max: Option<u32>, f: impl FnMut(&mut Unstructured<'a>) -> Result<ControlFlow<(), ()>, Error> ) -> Result<(), Error>

Call the given function an arbitrary number of times.

The function is given this Unstructured so that it can continue to generate arbitrary data and structures.

You may optionaly specify minimum and maximum bounds on the number of times the function is called.

You may break out of the loop early by returning Ok(std::ops::ControlFlow::Break). To continue the loop, return Ok(std::ops::ControlFlow::Continue).

Panics

Panics if min > max.

Example

Call a closure that generates an arbitrary type inside a context an arbitrary number of times:

use arbitrary::{Result, Unstructured};
use std::ops::ControlFlow;

enum Type {
    /// A boolean type.
    Bool,

    /// An integer type.
    Int,

    /// A list of the `i`th type in this type's context.
    List(usize),
}

fn arbitrary_types_context(u: &mut Unstructured) -> Result<Vec<Type>> {
    let mut context = vec![];

    u.arbitrary_loop(Some(10), Some(20), |u| {
        let num_choices = if context.is_empty() {
            2
        } else {
            3
        };
        let ty = match u.int_in_range::<u8>(1..=num_choices)? {
            1 => Type::Bool,
            2 => Type::Int,
            3 => Type::List(u.int_in_range(0..=context.len() - 1)?),
            _ => unreachable!(),
        };
        context.push(ty);
        Ok(ControlFlow::Continue(()))
    })?;

    // The number of loop iterations are constrained by the min/max
    // bounds that we provided.
    assert!(context.len() >= 10);
    assert!(context.len() <= 20);

    Ok(context)
}

Trait Implementations§

source§

impl<'a> Deref for Generator<'a>

§

type Target = Unstructured<'a>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<'a> DerefMut for Generator<'a>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<'a> From<&'a [u8]> for Generator<'a>

source§

fn from(bytes: &'a [u8]) -> Self

Converts to this type from the input type.
source§

impl<'a> From<Unstructured<'a>> for Generator<'a>

source§

fn from(arb: Unstructured<'a>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'a> RefUnwindSafe for Generator<'a>

§

impl<'a> Send for Generator<'a>

§

impl<'a> Sync for Generator<'a>

§

impl<'a> Unpin for Generator<'a>

§

impl<'a> UnwindSafe for Generator<'a>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more