# `Feel.Builtin.Size`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/builtin/size.ex#L1)

The size of what a built-in function is going to make, worked out before it makes it (D-154).

`max_list_length` and `max_string_length` refuse a value when it is finished (`Feel.Runtime.Env.settle/3`), which is
too late for a function whose result is as large as the product of the sizes of its arguments: `string join` of
5,000 strings of one byte with a delimiter of 100 KB makes 500 MB before the limit looks at it, and the limits would
allow 100 GB. Such a function works out the size first, counting as it walks its arguments and ending the walk at the
first count over the limit, and refuses with the function that `settle/3` uses (`Feel.Runtime.Env.check_string_length/2`,
`check_list_length/2`), so the error, the diagnostics in it and its effect on the run are the same as for the
finished value, in either mode and on either backend: the result that is within the limits is the one it always was,
and the one over them is refused with nothing built.

A count that is over a limit is a lower bound of the size of the result, and that is all the error says of it.

# `check_join`

```elixir
@spec check_join(Feel.Runtime.Env.t(), [String.t()], String.t(), non_neg_integer()) ::
  Feel.Runtime.Env.t()
```

Ends the run if the string that joins `items` with `delimiter` (and has `extra` more bytes, for a prefix and a suffix)
would be longer than `max_string_length`; the bytes are added up as the items come, so the walk ends at the first
item that passes the limit, and the string is not made. `items` are strings and not `null`.

    iex> env = Feel.Runtime.Env.new(limits: Feel.Limits.new(max_string_length: 5))
    iex> ^env = Feel.Builtin.Size.check_join(env, ["ab", "cd"], "+", 0)
    iex> {:error, error} = Feel.Runtime.Env.run(env, fn env -> {Feel.Builtin.Size.check_join(env, ["ab", "cd"], "+", 1), env} end)
    iex> {error.kind, hd(error.diagnostics).details}
    {:limit, %{limit: :max_string_length}}

# `refuse_list`

```elixir
@spec refuse_list(Feel.Runtime.Env.t(), non_neg_integer()) :: no_return()
```

Ends the run with the error of a list that is longer than `max_list_length`, for a function that has counted `length`
items of a list it was going to make. The same as `refuse_string/2` is for a string.

    iex> env = Feel.Runtime.Env.new(limits: Feel.Limits.new(max_list_length: 2))
    iex> {:error, error} = Feel.Runtime.Env.run(env, fn env -> {Feel.Builtin.Size.refuse_list(env, 3), env} end)
    iex> {error.kind, hd(error.diagnostics).details}
    {:limit, %{limit: :max_list_length}}

# `refuse_string`

```elixir
@spec refuse_string(Feel.Runtime.Env.t(), non_neg_integer()) :: no_return()
```

Ends the run with the error of a string that is longer than `max_string_length`, for a function that has found, with
`size` bytes counted, that the string it was going to make is. `size` is over the limit, and a call that is not
is a mistake of the caller.

    iex> env = Feel.Runtime.Env.new(limits: Feel.Limits.new(max_string_length: 5))
    iex> {:error, error} = Feel.Runtime.Env.run(env, fn env -> {Feel.Builtin.Size.refuse_string(env, 6), env} end)
    iex> {error.kind, hd(error.diagnostics).details}
    {:limit, %{limit: :max_string_length}}

---

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