Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jfacorro/Eden

edn (extensible data notation) encoder/decoder for Elixir
https://github.com/jfacorro/Eden

clojure edn elixir serialization

Last synced: about 1 month ago
JSON representation

edn (extensible data notation) encoder/decoder for Elixir

Awesome Lists containing this project

README

        

Eden
=====

[![GitHub](https://github.com/jfacorro/Eden/workflows/Build/badge.svg)](https://github.com/jfacorro/Eden/actions?query=workflow%3ABuild)
[![Hex.pm](https://img.shields.io/hexpm/v/eden.svg?style=flat-square)](https://hex.pm/packages/eden)
[![Hexdocs.pm](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/eden/)
[![Hex.pm](https://img.shields.io/hexpm/dt/eden.svg?style=flat-square)](https://hex.pm/packages/eden)
[![Hex.pm](https://img.shields.io/hexpm/l/eden.svg?style=flat-square)](https://hex.pm/packages/eden)
[![GitHub](https://img.shields.io/github/last-commit/jfacorro/Eden.svg)](https://github.com/jfacorro/Eden/commits/master)

[edn](https://github.com/edn-format/edn) (extensible data notation) encoder/decoder implemented in Elixir.

## Usage

Include Eden as a dependency in your Elixir project by adding it in your `deps` list:

```elixir
def deps do
[{:eden, "~> 0.1.2"}]
end
```

Eden is a library application and as such doesn't specify an application callback module. Even so, if you would like to build a release that includes Eden, you need to add it as an application dependency in your `mix.exs`:

```elixir
def application do
[applications: [:eden]]
end
```

## Examples

```elixir
iex> Eden.encode([1, 2])
{:ok, "(1, 2)"}

iex> Eden.encode(%{a: 1, b: 2, c: 3})
{:ok, "{:a 1, :b 2, :c 3}"}

iex> Eden.encode({:a, 1})
{:error, Protocol.UndefinedError}

iex> Eden.decode("{:a 1 :b 2}")
{:ok, %{a: 1, b: 2}}

iex> Eden.decode("(hello :world \\!)")
{:ok, [%Eden.Symbol{name: "hello"}, :world, %Eden.Character{char: "!"}]

iex> Eden.decode("[1 2 3 4]")
{:ok, #Array<[1, 2, 3, 4], fixed=false, default=nil>}

iex> Eden.decode("nil true false")
{:ok, [nil, true, false]}

iex> Eden.decode("nil true false .")
{:error, Eden.Exception.UnexpectedInputError}
```

## Data Structures Mapping: **edn** <-> **Elixir**

| Edn | Elixir |
|---|---|
| `nil` | `:nil = nil` |
| `true` | `:true = true` |
| `false` | `:false = false` |
| `string` | `String` |
| `character` | `Eden.Character` |
| `symbol` | `Eden.Symbol` |
| `keyword` | `Atom` |
| `integer` | `Integer` |
| `float` | `Float` |
| `list` | `List` |
| `vector` | `Array` |
| `map` | `Map` |
| `set` | `MapSet` |
| `#inst` | `Timex.DateTime` |
| `#uuid` | `Eden.UUID` |

## Further Considerations

### `Character`

There is no way of distinguishing a common integer from the representation of a character in a `String` or in `Char lists`. This forces the creation of a new representation for this type so it can be correctly translated from and to **edn**.

### Arbitrary Precision `Integer` and `Float`

The Erlang VM (EVM) only provides arbitrary precision integers so all integers will be of this type this and the `N` modifier will be ignored when parsing an **edn** integer.

On the other hand native arbitrary precision floating point numbers are not provided by the EVM so all values of type `float` will be represented according to what the EVM supports.

### `Keyword` and `Symbol` Representation

On one hand the decision to translate **edn** `keyword`s as Elixir `atom`s comes from the fact these two data types are given a similar usage on both languages. On the other, it might get awkward really fast using a new `Eden.Symbol` struct as the representation for **edn**'s `symbol`s so this might change.

### `vector`

There is no constant lookup or nearly constant indexed data structure like **edn**'s `vector` other than the `:array` data structure implemented in one of Erlang's standard library modules. Until there is a better implementation for this `Eden` will use [`Array`](https://github.com/takscape/elixir-array), an Elixir wrapper library for Erlang's array.

## **edn** grammar

```
expr -> literal | map | list | vector | tagged_value

literal -> nil | true | false | keyword | symbol | integer | float | string

map -> { pair* }
pair -> expr expr

list -> ( expr* )

vector -> [ expr* ]

tagged_value -> tag expr
```