[][src]Struct arbitrary::Unstructured

pub struct Unstructured<'a> { /* fields omitted */ }

A source of unstructured data.

An Unstructured helps Arbitrary implementations interpret raw data (typically provided by a fuzzer) as a "DNA string" that describes how to construct the Arbitrary type. The goal is that a small change to the "DNA string" (the raw data wrapped by an Unstructured) results in a small change to the generated Arbitrary instance. This helps a fuzzer efficiently explore the Arbitrary's input space.

Unstructured is deterministic: given the same raw data, the same series of API calls will return the same results (modulo system resource constraints, like running out of memory). However, Unstructured does not guarantee anything beyond that: it makes not guarantee that it will yield bytes from the underlying data in any particular order.

You shouldn't generally need to use an Unstructured unless you are writing a custom Arbitrary implementation by hand, instead of deriving it. Mostly, you should just be passing it through to nested Arbitrary::arbitrary calls.

Example

Imagine you were writing a color conversion crate. You might want to write fuzz tests that take a random RGB color and assert various properties, run functions and make sure nothing panics, etc.

Below is what translating the fuzzer's raw input into an Unstructured and using that to generate an arbitrary RGB color might look like:

use arbitrary::{Arbitrary, Unstructured};

/// An RGB color.
#[derive(Arbitrary)]
pub struct Rgb {
    r: u8,
    g: u8,
    b: u8,
}

// Get the raw bytes from the fuzzer.
let raw_data: &[u8] = get_input_from_fuzzer();

// Wrap it in an `Unstructured`.
let mut unstructured = Unstructured::new(raw_data);

// Generate an `Rgb` color and run our checks.
if let Ok(rgb) = Rgb::arbitrary(&mut unstructured) {
    run_my_color_conversion_checks(rgb);
}

Methods

impl<'a> Unstructured<'a>[src]

pub fn new(data: &'a [u8]) -> Self[src]

Create a new Unstructured from the given raw data.

Example

use arbitrary::Unstructured;

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

pub fn len(&self) -> usize[src]

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);

pub fn is_empty(&self) -> bool[src]

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());

pub fn arbitrary<A>(&mut self) -> Result<A> where
    A: Arbitrary
[src]

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);

pub fn arbitrary_len<ElementType>(&mut self) -> Result<usize> where
    ElementType: Arbitrary
[src]

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<T> Arbitrary for MyCollection<T>
where
    T: Arbitrary,
{
    fn arbitrary(u: &mut Unstructured<'_>) -> 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)
    }
}

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

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);

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

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.

Panics

Panics if choices is empty.

Example

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'];
if let Ok(ch) = u.choose(&choices) {
    println!("chose {}", ch);
}

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

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 data to fill the whole buffer, an error is returned.

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!(u.fill_buffer(&mut buf).is_ok());
assert!(u.fill_buffer(&mut buf).is_err());

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

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.get_bytes(2).unwrap() == &[1, 2]);
assert!(u.get_bytes(2).unwrap() == &[3, 4]);

pub fn take_rest(self) -> &'a [u8][src]

Consume all of the rest of the remaining underlying bytes.

Returns a slice of all the remaining, unconsumed bytes.

Example

use arbitrary::Unstructured;

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

let mut remaining = u.take_rest();

assert_eq!(remaining, [1, 2, 3]);

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

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()

pub fn arbitrary_take_rest_iter<ElementType: Arbitrary>(
    self
) -> Result<ArbitraryTakeRestIter<'a, ElementType>>
[src]

Provide an iterator over elements for constructing a collection from all the remaining bytes.

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

Auto Trait Implementations

impl<'a> RefUnwindSafe for Unstructured<'a>

impl<'a> Send for Unstructured<'a>

impl<'a> Sync for Unstructured<'a>

impl<'a> Unpin for Unstructured<'a>

impl<'a> UnwindSafe for Unstructured<'a>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.