# `Lotus.Storage.TypeCaster`
[🔗](https://github.com/typhoonworks/lotus/blob/v0.16.6/lib/lotus/storage/type_caster.ex#L1)

Casts variable values to appropriate types based on database column types.

Automatically converts string values from web UI inputs to the correct database types.
Provides clear error messages when values cannot be cast to the expected type.

## UUID Handling

For PostgreSQL UUID columns, we must convert string UUIDs to 16-byte binary format.
Postgrex expects: `<<160,238,188,153,156,11,78,248,187,109,107,185,189,56,10,17>>`

We use `Ecto.UUID.dump/1` which works for:
- Standard UUIDs (v4)
- UUIDv7 (delegates to Ecto.UUID)
- Any other UUID type that follows RFC 9562 format

See: https://hexdocs.pm/ecto/Ecto.UUID.html#dump/1

## Usage

    # Cast UUID string to binary
    TypeCaster.cast_value("550e8400-e29b-41d4-a716-446655440000", :uuid, %{table: "users", column: "id"})
    # => {:ok, <<85, 14, 132, 0, ...>>}

    # Cast integer string to integer
    TypeCaster.cast_value("42", :integer, %{table: "users", column: "age"})
    # => {:ok, 42}

    # Invalid cast returns error
    TypeCaster.cast_value("not-a-uuid", :uuid, %{table: "users", column: "id"})
    # => {:error, "Failed to cast value for variable bound to users.id..."}

# `cast_value`

```elixir
@spec cast_value(
  value :: term(),
  lotus_type :: Lotus.Storage.TypeMapper.lotus_type() | String.t(),
  column_info :: %{column: String.t(), table: String.t()}
) :: {:ok, term()} | {:error, String.t()}
```

Cast a value to match the expected column type.

First checks for custom type handlers registered via Application config.
Falls back to built-in type casting if no custom handler is found.

Returns `{:ok, cast_value}` on success or `{:error, reason}` on failure.

## Examples

    cast_value("550e8400-e29b-41d4-a716-446655440000", :uuid, %{table: "users", column: "id"})
    # => {:ok, <<85, 14, 132, ...>>}

    cast_value("42", :integer, %{table: "users", column: "age"})
    # => {:ok, 42}

    cast_value("true", :boolean, %{table: "users", column: "active"})
    # => {:ok, true}

## Custom Type Handlers

You can register custom handlers in your config:

    config :lotus, :type_handlers, %{
      "my_enum" => MyApp.MyEnumHandler
    }

When a database type name (string) is passed instead of a Lotus type (atom),
the registry is checked first before mapping to a Lotus type.

---

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