README.md

# Eyeon

An Elixir library for encoding and decoding [Amazon Ion](https://amazon-ion.github.io/ion-docs/) data.

Supports both Ion text (`.ion`) and Ion binary (`.10n`) formats, with auto-detection of binary input on decode. Passes Amazon's official Ion conformance test suite for Ion 1.0 and 1.1.

Note I have made no great effort to make this actually performant. In fact, it's pretty slow compared to something like the [Jason](https://github.com/michalmuskala/jason)) library. See [benchmarks][./bench/README.md] for more info.

## Installation

Add `eyeon` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:eyeon, "~> 0.1.0"}
  ]
end
```

## Usage

```elixir
# Decode Ion text
{:ok, value} = Eyeon.decode("{name: \"Alice\", scores: [98, 87, 95]}")
value["name"]  #=> "Alice"

# Encode to Ion text (default)
{:ok, ion} = Eyeon.encode(%{"greeting" => "hello"})

# Encode to Ion binary
{:ok, bin} = Eyeon.encode(42, %{encoding: :binary})

# Round-trip through files
File.write!("user.ion", Eyeon.encode!(%{"name" => "Alice", "age" => 30}))
Eyeon.decode!(File.read!("user.ion"))
#=> %{"age" => 30, "name" => "Alice"}
```

## Ion type mapping

Most Ion types map directly to Elixir types. Types without a native equivalent use tagged tuples:

| Ion type    | Elixir representation                              |
|-------------|-----------------------------------------------------|
| `null`      | `nil`                                               |
| `bool`      | `true` / `false`                                    |
| `int`       | integer                                             |
| `float`     | float, `:nan`, `:infinity`, `:neg_infinity`         |
| `decimal`   | `Decimal.t()`                                       |
| `timestamp` | `DateTime.t()`, `NaiveDateTime.t()`, or `Date.t()` |
| `string`    | binary string                                       |
| `symbol`    | `{:symbol, name}`                                   |
| `blob`      | `{:blob, binary}`                                   |
| `clob`      | `{:clob, binary}`                                   |
| `list`      | list                                                |
| `struct`    | map with string keys                                |
| `sexp`      | `{:sexp, list}`                                     |
| `annotation`| `{:annotated, {:symbol, name}, value}`              |
| typed null  | `{:null, type}` e.g. `{:null, :int}`               |

## Timestamps

By default, Ion timestamps decode to native Elixir date/time types based on their precision and offset:

```elixir
Eyeon.decode!("2024-01-15T12:30:00Z")
#=> ~U[2024-01-15 12:30:00Z]

Eyeon.decode!("2024-01-15")
#=> ~D[2024-01-15]
```

Pass `%{timestamp: :raw}` to get `{:timestamp, string}` tuples that preserve the original Ion precision and offset semantics:

```elixir
Eyeon.decode!("2024-01-15T12:30:00Z", %{timestamp: :raw})
#=> {:timestamp, "2024-01-15T12:30:00Z"}
```

## Documentation

Full documentation is available at [hexdocs.pm/eyeon](https://hexdocs.pm/eyeon).

## Development

### Updating `ion-tests`

Add the `ion-tests` remote, if needed:
```
git remote add -f ion-tests https://github.com/amazon-ion/ion-tests
```

Then pull/fetch:
```
git fetch ion-tests main

git subtree pull --prefix test/ion-tests ion-tests main --squash
```

## License

MIT - see [LICENSE](LICENSE) for details.