# `Enviable.Conversion`
[🔗](https://github.com/halostatue/enviable/blob/v2.3.0/lib/enviable/conversion.ex#L1)

All supported conversions and options for those conversions.

# `conversion`
*since 1.1.0* 

```elixir
@type conversion() :: primitive() | encoded()
```

All supported conversions.

# `convert_atom`
*since 1.1.0* 

```elixir
@type convert_atom() :: :atom
```

Indicates a conversion to `t:atom/0`.

> #### Untrusted Input {: .warning}
>
> This conversion uses `String.to_atom/1` and may result in atom exhaustion if used
> without the `:allowed` option. See [Preventing atom exhaustion](https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/atom_exhaustion) from the Security Working Group
> of the Erlang Ecosystem Foundation.

### Options

- `:allowed`: A list of `t:atom/0` values indicating permitted atoms and used as
  a lookup table, if present. Any value not found will result in an exception.

- `:default`: The `t:atom/0` or `t:binary/0` value representing the atom value to use if
  the environment variable is unset (`nil`). If the `:allowed` option is present, the
  default value must be one of the permitted values.

- `:downcase`: See `t:opt_atom_downcase/0`.

- `:upcase`: See `t:opt_atom_upcase/0`.

# `convert_boolean`
*since 1.0.0* 

```elixir
@type convert_boolean() :: :boolean
```

Indicates a conversion to `t:boolean/0`. This conversion will always result in a `true`
or `false` value.

### Options

- `:default`: The default value, which must be `true` or `false`. The default value is
  `false`.
- `:downcase`: This option controls a type conversion's case folding mode passed to
  `String.downcase/2`. The default is `:default`. `true` has the same meaning as
  `:default`.

  The default `:downcase` value for boolean conversions can be changed at compile time
  through application configuration:

  ```elixir
  config :enviable, :boolean_downcase, true
  config :enviable, :boolean_downcase, :default
  config :enviable, :boolean_downcase, :ascii
  ```

- `:truthy`, `:falsy`: Only one of `:truthy` or `:falsy` may be specified. It must be
  a list of `t:binary/0` values. If neither is specified, the default is
  `truthy: ~w[1 true]`.

  - `:truthy`: if the value to convert is in this list, the result is `true`

  - `:falsy`: if the value to convert is in this list, the result is `false`

# `convert_charlist`
*since 1.1.0* 

```elixir
@type convert_charlist() :: :charlist
```

Indicates a conversion to `t:charlist/0`.

### Options

- `:default`: The default value, either as a `t:charlist/0` or `t:binary/0`.

# `convert_decimal`
*since 1.6.0* 

```elixir
@type convert_decimal() :: :decimal
```

Indicates a conversion to `t:Decimal.t/0`.

### Options

- `:default`: The default value, either as `t:Decimal.t/0`, `t:float/0`, `t:integer/0`,
  or `t:binary/0` (the latter three must convert cleanly to `t:Decimal.t/0`).

# `convert_duration`
*since 2.2.0* 

```elixir
@type convert_duration() :: :duration
```

Indicates a conversion to `t:Duration.t/0`.

# `convert_elixir`
*since 1.3.0* 

```elixir
@type convert_elixir() :: :elixir
```

Indicates a conversion from a Elixir code string (`:elixir`) by parsing and evaluating
the environment variable value.

This can be used for tuples, complex map declarations, or other expressions difficult to
represent with other types. Longer code blocks should be encoded as base 64 text and
decoded as `{:base64, :elixir}`.

> #### Untrusted Input {: .error}
>
> This function parses (with `Code.string_to_quoted/1`) and evaluates (with
> `Code.eval_quoted/1`) elixir code from environment variables in the context of your
> application. Do not use this with untrusted input.

## Examples

```elixir
iex> Enviable.put_env("PORT", "11000..11100//3")
iex> Enviable.get_env_as("PORT", :elixir)
11000..11100//3
```

# `convert_erlang`
*since 1.1.0* 

```elixir
@type convert_erlang() :: :erlang
```

Indicates a conversion from a Erlang code string (`:erlang`) by parsing and evaluating
the environment variable value.

This can be used for tuples, complex map declarations, or other expressions difficult to
represent with other types. Longer code blocks should be encoded as base 64 text and
decoded as `{:base64, :erlang}`.

> #### Untrusted Input {: .error}
>
> This function parses (with `:erl_scan.string/1`) and evaluates (with
> `:erl_parse.parse_term/1`) Erlang code from environment variables in the context of
> your application. Do not use this with untrusted input.

## Examples

```elixir
iex> Enviable.put_env("COLOR", "{ok, true}.")
iex> Enviable.get_env_as("COLOR", :erlang)
{:ok, true}
```

# `convert_float`
*since 1.1.0* 

```elixir
@type convert_float() :: :float
```

Indicates a conversion to `t:float/0`.

### Options

- `:default`: The default value, either as `t:float/0`, `t:integer/0` (converted to
  float), or `t:binary/0` (which must parse cleanly as float).

# `convert_integer`
*since 1.0.0* 

```elixir
@type convert_integer() :: :integer
```

Indicates a conversion to `t:integer/0`.

### Options

- `:base`: The base (an integer value `2..36`). Default is `10`.

- `:default`: The default value. If specified as a `t:binary/0`, it must be expressed in
  the `:base` value and convert cleanly to an integer.

# `convert_json`
*since 1.1.0* 

```elixir
@type convert_json() :: :json
```

Indicates a conversion from JSON, which may result in `nil`, `t:binary/0`,
`t:boolean/0`, `t:list/0`, `t:map/0`, or `t:number/0` values.

### Options

- `:default`: The default value, which may be any valid JSON type.

- `:engine`: The JSON engine to use. May be provided as a `t:module/0` (which must
  export `decode/1`), an arity 1 function, or a `t:mfa/0` tuple. When provided with
  a `t:mfa/0`, the variable value is passed as the first parameter.

  If the engine produces `{:ok, json_value}` or an expected JSON type result, it is
  considered successful. Any other result is treated as failure.

  The default JSON module is selected from the `:enviable` application configuration
  option `:json_engine`. If this is unset, the default value is one of the following, in
  order:

  - [`JSON`][elixir-json] if the Elixir `m:JSON` module is available (Elixir 1.18+)
  - `:json` if the Erlang/OTP 27+ `m::json` module is available or if
    [json_polyfill][jp] is installed
  -  [Jason][jason]

  This example shows using [Thoas][thoas] as the JSON engine.

  ```elixir
  import Config

  config :enviable, :json_engine, :thoas
  ```

[elixir-json]: https://hexdocs.pm/elixir/JSON.html
[jp]: https://hexdocs.pm/json_polyfill/readme.html
[jason]: https://hexdocs.pm/jason/readme.html
[thoas]: https://hexdocs.pm/thoas/readme.html

# `convert_log_level`
*since 1.2.0* 

```elixir
@type convert_log_level() :: :log_level
```

Indicates a conversion to log level `t:atom/0` for `Logger.configure/1`.

This conversion is always case-insensitive, and the result is one of `:emergency`,
`:alert`, `:critical`, `:error`, `:warning`, `:notice`, `:info`, `:debug`, `:all`, or
`:none`.

### Options

- `:default`: The default atom value. Must be a valid value.

# `convert_module`
*since 1.1.0* 

```elixir
@type convert_module() :: :module
```

Indicates a conversion to `t:module/0`.

> #### Untrusted Input {: .warning}
>
> This conversion uses `Module.concat/1` and may result in atom exhaustion if used
> without the `:allowed` option. See [Preventing atom exhaustion](https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/atom_exhaustion) from the Security Working Group
> of the Erlang Ecosystem Foundation.

### Options

- `:allowed`: A list of `t:module/0` values indicating permitted module and used as
  a lookup table, if present. Any value not found will result in an exception.

- `:default`: The `t:module/0` or `t:binary/0` value representing the atom value to use
  if the environment variable is unset (`nil`). If the `:allowed` option is present, the
  default value must be one of the permitted values.

# `convert_pem`
*since 1.1.0* 

```elixir
@type convert_pem() :: :pem
```

Indicates a conversion from a PEM string through `:public_key.pem_decode/1`.

### Options

- `:filter`: Filters the output of `:public_key.pem_decode/1`. Permitted values are
  `false`, `true`, `:cert`, or `:key`. The default is `true`.

  - `false`: the list is returned without processing, suitable for further processing
    with `:public_key.pem_entry_decode/2`.

  - `true`: returns the first unencrypted `:PrivateKeyInfo` found, a list of unencrypted
    `:Certificate` records, or an empty list.

  - `:cert`: returns a list of unencrypted `:Certificate` records or raises an exception
    if none are found.

  - `:key`: returns the first unencrypted `:PrivateKeyIinfo` record or raises an
    exception if one is not found.

# `convert_safe_atom`
*since 1.1.0* 

```elixir
@type convert_safe_atom() :: :safe_atom
```

Indicates a conversion to `t:atom/0`.

> #### Untrusted Input {: .warning}
>
> This conversion uses `String.to_existing_atom/1` which will result in an exception if
> the resulting atom is not already known and if used without the `:allowed` option. See
> [Preventing atom exhaustion](https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/atom_exhaustion) from the Security Working Group of the Erlang Ecosystem Foundation.

### Options

- `:allowed`: A list of `t:atom/0` values indicating permitted atoms and used as
  a lookup table, if present. Any value not found will result in an exception.

- `:default`: The `t:atom/0` or `t:binary/0` value representing the atom value to use if
  the environment variable is unset (`nil`). If the `:allowed` option is present, the
  default value must be one of the permitted values.

- `:downcase`: See `t:opt_atom_downcase/0`.

- `:upcase`: See `t:opt_atom_upcase/0`.

# `convert_safe_module`
*since 1.1.0* 

```elixir
@type convert_safe_module() :: :safe_module
```

Indicates a conversion to `t:module/0`.

> #### Untrusted Input {: .warning}
>
> This conversion uses `Module.safe_concat/1` which will result in an exception if the
> resulting module is not already known and if used without the `:allowed` option. See
> [Preventing atom exhaustion](https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/atom_exhaustion) from the Security Working Group of the Erlang Ecosystem Foundation.

### Options

- `:allowed`: A list of `t:module/0` values indicating permitted module and used as
  a lookup table, if present. Any value not found will result in an exception.

- `:default`: The `t:module/0` or `t:binary/0` value representing the atom value to use
  if the environment variable is unset (`nil`). If the `:allowed` option is present, the
  default value must be one of the permitted values.

# `convert_timeout`
*since 1.7.0* 

```elixir
@type convert_timeout() :: :timeout
```

Indicates a conversion to `t:timeout/0`.

### Timeout Values

Timeout values are either ISO8601 duration strings (like `PT30M` for a 30 minute
duration, see `Duration.from_iso8601/1`), the word `infinity`, or a non-negative integer
value with optional suffixes. The integer part may have underscores (`_`) separating
digits like Elixir itself.

If no suffix is present, the value is in milliseconds. Supported suffixes are:

- `week`, `weeks`, `w`: the number of weeks (always 7 days)
- `day`, `days`, `d`: the number of days (always 24 hours)
- `hour`, `hours`, `h`: the number of hours (always 60 minutes)
- `minute`, `minutes`, `m`: the number of minutes (always 60 seconds)
- `second`, `seconds`, `s`: the number of seconds (always 1000 milliseconds)
- `millisecond`, `milliseconds`, `ms`: the number of milliseconds

Suffixes may be present with or without a space (`30s` and `30 s` are the same value),
and multiple timeouts may be chained (`1h 30m`), but may not be duplicated. Only
lowercase suffixes are supported.

See `Kernel.to_timeout/1` for more details.

# `encoded`
*since 1.1.0* 

```elixir
@type encoded() ::
  encoded_base16()
  | encoded_base32()
  | encoded_hex32()
  | encoded_base64()
  | encoded_list()
```

All supported encoded conversions.

# `encoded_base16`
*since 1.1.0* 

```elixir
@type encoded_base16() :: :base16 | {:base16, :string | primitive()}
```

Decodes the value from a base 16 encoded string.

If a secondary type is provided, a further conversion pass is made using the secondary
type.

### Options

- `:case`: The value of `:case` passed to `Base.decode16/2`, which must be `:upper`,
  `:lower`, or `:mixed`. The default is `:mixed`.

If a secondary type is provided, the options for that type may also be provided.

# `encoded_base32`
*since 1.1.0* 

```elixir
@type encoded_base32() :: :base32 | {:base32, :string | primitive()}
```

Decodes the value from a base 32 encoded string.

If a secondary type is provided, a further conversion pass is made using the secondary
type.

### Options

- `:case`: The value of `:case` passed to `Base.decode32/2`, which must be `:upper`,
  `:lower`, or `:mixed`. The default is `:mixed`.

- `:padding`: The boolean value of `:padding` passed to `Base.decode32/2`. The default
  is `false` (the opposite of `Base.decode32/2`).

If a secondary type is provided, the options for that type may also be provided.

# `encoded_base64`
*since 1.1.0* 

```elixir
@type encoded_base64() ::
  :base64 | :url_base64 | {:base64 | :url_base64, :string | primitive()}
```

Decodes the value from a base 64 encoded string.

If a secondary type is provided, a further conversion pass is made using the secondary
type.

### Options

- `:ignore_whitespace`: Whether to ignore whitespace values. The default is `true`,
  the opposite default for both `Base.decode64/2` and `Base.url_decode64/2`.

- `:padding`: The boolean value of `:padding` passed to `Base.decode64/2`. The default
  is `false` (the opposite of `Base.decode64/2`).

If a secondary type is provided, the options for that type may also be provided.

# `encoded_hex32`
*since 1.1.0* 

```elixir
@type encoded_hex32() :: :hex32 | {:hex32, :string | primitive()}
```

Decodes the value from a base 32 hex encoded string with extended hexadecimal alphabet.

If a secondary type is provided, a further conversion pass is made using the secondary
type.

### Options

- `:case`: The value of `:case` passed to `Base.hex_decode32/2`, which must be `:upper`,
  `:lower`, or `:mixed`. The default is `:mixed`.

- `:padding`: The boolean value of `:padding` passed to `Base.hex_decode32/2`. The
  default is `false` (the opposite of `Base.hex_decode32/2`).

If a secondary type is provided, the options for that type may also be provided.

# `encoded_list`
*since 1.4.0* 

```elixir
@type encoded_list() :: :list | {:list, :string | primitive()}
```

Decodes the value from a string as a delimiter-separated list.

If a secondary type is provided, a further conversion pass is made using the secondary
type.

### Options

- `:delimiter`: The delimiter used to separate the list. This must be a pattern accepted
  by `String.split/3` (a string, a list of strings, a compiled binary pattern, or
  a regular expression). Defaults to `","`.

- `:parts`: The maximum number of parts to split into (`t:pos_integer/0` or
  `:infinity`). Passed to `String.split/3`.

- `:trim`: A boolean option whether empty entries should be omitted.

When the pattern is a regular expression, `Regex.split/3` options are also supported:

- `:on`: specifies which captures to split the string on, and in what order. Defaults to
  :first which means captures inside the regex do not affect the splitting process.

- `:include_captures`: when true, includes in the result the matches of the regular
  expression. The matches are not counted towards the maximum number of parts if
  combined with the `:parts` option. Defaults to `false`.

If a secondary type is provided, the options for that type may also be provided.

# `json`

```elixir
@type json() ::
  nil
  | String.t()
  | boolean()
  | number()
  | [json()]
  | %{optional(String.t()) =&gt; json()}
```

A value which can be serialized from JSON.

# `log_level`
*since 1.3.0* 

```elixir
@type log_level() :: Logger.level() | :all | :none
```

Supported log levels.

# `opt_atom_downcase`
*since 2.0.0* 

```elixir
@type opt_atom_downcase() ::
  {:downcase, true | false | :default | :ascii | :greek | :turkic}
```

This option controls atom conversion case folding mode passed to `String.downcase/2`.

The default is `false`. `true` has the same meaning as `:default`.

This is mutually exclusive with `upcase`.

# `opt_atom_upcase`
*since 2.0.0* 

```elixir
@type opt_atom_upcase() ::
  {:upcase, true | false | :default | :ascii | :greek | :turkic}
```

This option controls a atom conversion case folding mode passed to `String.upcase/2`.

The default is `false`. `true` has the same meaning as `:default`.

This is mutually exclusive with `downcase`.

# `opt_bool_downcase`
*since 2.0.0* 

```elixir
@type opt_bool_downcase() ::
  {:downcase, true | false | :default | :ascii | :greek | :turkic}
```

This option controls boolean conversion case folding mode passed to `String.downcase/2`.

The default is `false`. `true` has the same meaning as `:default`.

# `opt_encoded_case`
*since 2.0.0* 

```elixir
@type opt_encoded_case() :: {:case, :lower | :mixed | :upper}
```

This option controls case sensitivity processing for `t:encoded_base16/0`,
`t:encoded_base32/0`, or `t:encoded_hex32/0`.

The default is `:mixed`.

# `pem`
*since 1.3.0* 

```elixir
@type pem() ::
  [:public_key.pem_entry()]
  | binary()
  | [{:Certificate, binary(), :not_encrypted}]
```

Possible return types for `t:convert_pem/0` conversions.

The return types are variant on the conversion `:filter` option value:

- `true`: either an unencrypted primary key `t:binary/0` or a list of unencrypted
  certificates (`[{:Certificate, ct, :not_encrypted}]`);

- `false`: an unmodified list of `t::public_key.pem_entry/0`.

- `:cert`: list of unencrypted certificates (`[{:Certificate, ct, :not_encrypted}]`).

- `:key`: unencrypted primary key `t:binary/0`

The default is `true`.

# `primitive`
*since 1.1.0* 

```elixir
@type primitive() ::
  convert_atom()
  | convert_boolean()
  | convert_charlist()
  | convert_decimal()
  | convert_elixir()
  | convert_erlang()
  | convert_float()
  | convert_integer()
  | convert_json()
  | convert_module()
  | convert_pem()
  | convert_safe_atom()
  | convert_safe_module()
  | convert_timeout()
```

All supported primitive conversions.

# `timeout_default`
*since 1.7.0* 

```elixir
@type timeout_default() ::
  binary()
  | {:week | :day | :hour | :minute | :second | :millisecond, non_neg_integer()}
  | timeout()
  | Duration.t()
```

Supported default values for timeout conversions.

---

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