# `Rupa.Gen`
[🔗](https://github.com/zero-one-group/rupa/blob/v0.1.0/lib/rupa/gen.ex#L2)

StreamData generators built from a schema, for the round-trip property.

Add `stream_data` to your own deps to use this — Rupa lists it as optional, so it is not
forced on anyone who only wants to decode.

    property "encode and decode are inverses" do
      codec = Rupa.compile!(MyApp.Schemas.user())

      check all value <- Rupa.Gen.stream(codec) do
        assert {:ok, wire} = Rupa.encode(codec, value)
        assert {:ok, ^value} = Rupa.decode(codec, wire)
      end
    end

What it generates is **decoded** values — what `Rupa.decode/3` returns and `Rupa.encode/3`
takes — because that is the side the property is stated on. A field carrying `default:`
is always generated, even though it is optional on the wire: leave it out and decoding
fills it in, and the value that comes back is not the one you started with.

## What it refuses

A generator that quietly skips half your schema is worse than one that will not start, so
these raise with the path rather than being ignored:

  * `pattern:` — generating a string from a PCRE is a project of its own
  * `multiple_of:` on a float, or one that is not a whole number on an integer — the
    multiples of `0.1` are not representable, so the values it produced would fail the
    check they were generated to satisfy
  * a bound that nothing satisfies, such as `T.integer(gt: 1, lt: 2)` or a float interval
    with no double in it
  * a recursion with no case that stops, such as `%{child: T.ref(:root)}`, which has no
    finite value at all

## Untagged unions

An untagged union generates from one of its variants at random, which round-trips only if
the variants are disjoint — if two of them accept the same value, decoding picks the first
and the property will tell you so. That is the cost `tag: :none` makes you opt into, and
`Rupa.T.tagged/3` is the version with nothing to be ambiguous about.

# `stream`

```elixir
@spec stream(term()) :: StreamData.t(term())
```

A generator of decoded values for a codec, a generated module, or a schema.

    iex> [value] = %{n: Rupa.T.integer(gte: 1, lte: 3)} |> Rupa.Gen.stream() |> Enum.take(1)
    iex> value.n in 1..3
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
