# decode

[![](]( [![](](

A Gleam library for transforming Erlang or Elixir data into Gleam data.

`decode` allows you to build `Decoder`s, which can then be used to transform
data from Erlang or Elixir into type-safe Gleam data!

## Getting started

If you're only concerned with decoding data from one of either Elixir or Erlang,
skip ahead to the relevant section, and then read the Gleam example.

### Elixir

Let's say that you have an Elixir struct that you'd like to work with in your
Gleam code.

%User{name: "Jose Valim", age: 25}

Remember that under the hood, Elixir structs are just maps with a `__struct__`
field, and module names are just atoms!

%{__struct__: Elixir.User, name: "Jose Valim", age: 25}

So you have an Elixir function that returns one of these User structs, that
you'd like to use in your Gleam code.

# user.ex

@spec get_user() :: User.t()

### Erlang

Let's say that you have an Erlang record that you'd like to work with in your
Gleam code.

-record(user, {name :: string(), age :: non_neg_integer()}).

Remember that Erlang records are just tagged tuples under the hood!

{user, "Joe Armstrong", 35}

So you have an Erlang function that returns one of these user records.

%% user.erl

-spec get_user() -> user()

### Gleam

In order to translate this Elixir or Erlang data into a format that Gleam can
work with, we'll need to explain to Gleam how it maps onto Gleam types, and
probably define some custom types in the process.

// user.gleam

import decode.{Decoder, decode_dynamic, atom_field, element, map2, int, string}

// First, we define the Gleam type that we'd like to transform this data into.
pub type User {
    name: String,
    age: Int

// Second, we define a decoder that will be used to transform an Elixir User
// struct into our custom Gleam type.
pub fn ex_user_decoder() -> Decoder(User) {
    atom_field("name", string()),
    atom_field("age", int())

// Or an Erlang user record into our custom Gleam type.
pub fn erl_user_decoder() -> Decoder(User) {
    element(1, string()),
    element(2, int())

// Third, we create an external function that calls the Elixir function
// that returns a User struct.
fn external ex_external_get_user() -> Dynamic
  = "Elixir.User" "get_user"

// Or the Erlang function that returns a user record.
fn external erl_external_get_user() -> Dynamic
  = "user" "get_user"

// And finally, we write the functions that perform the decoding!
pub fn ex_create_user() -> Result(User, String) {
  |> decode_dynamic(ex_user_decoder())

pub fn erl_create_user() -> Result(User, String) {
  |> decode_dynamic(erl_user_decoder())

## Installation

Add `gleam_decode` to the deps section of your `rebar.config` file.

{deps, [
    {gleam_decode, "1.7.0"}

## Need help?

If you are having trouble understanding how to use this library, or find
yourself dealing with a decoding problem that you don't believe is solvable with
the current API, please open an issue!

## Credit

Most of this library is based on the Elm language's JSON decoding library
([elm/json][1]), with some attention paid also to the community-driven "JSON
extras" library ([elm-community/json-extra][2]). Thanks to them for the great