🧪
ElixirからTOML v1.0.0のファイルを扱えるライブラリを調べる
はじめに
2021年の1月にTOML v1.0.0がリリースされたようです。
v0.5.0からv1.0.0-rc.1、v1.0.0-rc.2、v1.0.0-rc.3を経ての正式バージョンのリリースです。
この記事では、ElixirでTOML v1.0.0を使えるライブラリを調べてみました。
v0.5.0とv1.0.0の違い
下記の和訳されたドキュメントを比較しましたが、自分が見つけられた記述面の違いは下記の1つだけでした。
後ほど改めて英語版のv1.0.0のドキュメントと比較してみます。
Elixirライブラリの対応状況
TOMLは各バージョンごとに対応するプログラミング言語のライブラリを公式GitHubのwikiページに掲載しています。
以下の表は、上記のwikiページからElixirから呼べるライブラリを抜き出したものです。
ライブラリ名 | 対応TOMLバージョン |
---|---|
toml | v0.5.0 |
tomerl | v1.0.0 |
各ライブラリの動きを試す
先述の表にあるライブラリで、v1.0.0とv0.5.0の仕様で記述されたTOMLファイルをパースできるか比較してみます。
まず、下記のファイルはTOML公式GitHubにも記載されているサンプルデータです。
v0.5.0でも解釈できる記述で書かれている(はず)
sample.toml
# This is a TOML document.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates
[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# Indentation (tabs and/or spaces) is allowed but not required
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ]
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
こちらは、v1.0.0-rc2のドキュメントに掲載されている"配列中に複数種類のデータ型を含んだ配列"を持つTOMLファイルになります。
v1.0.0.toml
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_array_of_int = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]
# 異なる型を混ぜて使うこともできます。
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
"Foo Bar <foo@example.com>",
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]
TOML(Elixir)
$ iex -S mix
# v0.5.0対応のファイルはパース成功
iex(1)> File.read!("sample.toml") |> Toml.decode!
%{
"clients" => %{
"data" => [["gamma", "delta"], [1, 2]],
"hosts" => ["alpha", "omega"]
},
"database" => %{
"connection_max" => 5000,
"enabled" => true,
"ports" => [8000, 8001, 8002],
"server" => "192.168.1.1"
},
"owner" => %{
"dob" => ~U[1979-05-26 23:32:00Z],
"name" => "Tom Preston-Werner"
},
"servers" => %{
"alpha" => %{"dc" => "eqdc10", "ip" => "10.0.0.1"},
"beta" => %{"dc" => "eqdc10", "ip" => "10.0.0.2"}
},
"title" => "TOML Example"
}
# v1.0.0の記述を書いたファイルはパース失敗(バージョン未対応なので想定通り)
iex(2)> File.read!("v1.0.0.toml") |> Toml.decode!
** (EXIT from #PID<0.210.0>) shell process exited with reason: an exception was raised:
** (ArgumentError) argument error
(stdlib 3.15.2) :io.put_chars(:standard_io, :unicode, [[<<27, 91, 51, 49, 109, 42, 42, 32, 40, 84, 111, 109, 108, 46, 69, 114, 114, 111, 114, 41, 32, 123, 58, 105, 110, 118, 97, 108, 105, 100, 95, 97, 114, 114, 97, 121, 44, 32, 123, 58, 101, 120, 112, 101, 99, 116, 101, 100, ...>>], 10, "\e[31m (toml 0.6.2) lib/decoder.ex:50: Toml.Decoder.decode!/2\n\e[0m"])
(iex 1.12.2) lib/iex/evaluator.ex:266: IEx.Evaluator.eval/3
(iex 1.12.2) lib/iex/evaluator.ex:157: IEx.Evaluator.loop/1
(iex 1.12.2) lib/iex/evaluator.ex:32: IEx.Evaluator.init/4
(stdlib 3.15.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
tomerl
$ iex -S mix
# v0.5.0対応のファイルはパース成功
iex(1)> File.read!("sample.toml") |> :tomerl.parse
{:ok,
%{
"clients" => %{
"data" => [["gamma", "delta"], [1, 2]],
"hosts" => ["alpha", "omega"]
},
"database" => %{
"connection_max" => 5000,
"enabled" => true,
"ports" => [8000, 8001, 8002],
"server" => "192.168.1.1"
},
"owner" => %{
"dob" => {:datetime_offset, {:date, 1979, 5, 27}, {:time, 7, 32, 0}, -480},
"name" => "Tom Preston-Werner"
},
"servers" => %{
"alpha" => %{"dc" => "eqdc10", "ip" => "10.0.0.1"},
"beta" => %{"dc" => "eqdc10", "ip" => "10.0.0.2"}
},
"title" => "TOML Example"
}}
# v1.0.0の記述を書いたファイルもパース成功
iex(2)> File.read!("v1.0.0.toml") |> :tomerl.parse
{:ok,
%{
"colors" => ["red", "yellow", "green"],
"contributors" => [
"Foo Bar <foo@example.com>",
%{
"email" => "bazqux@example.com",
"name" => "Baz Qux",
"url" => "https://example.com/bazqux"
}
],
"integers" => [1, 2, 3],
"nested_array_of_int" => [[1, 2], [3, 4, 5]],
"nested_mixed_array" => [[1, 2], ["a", "b", "c"]],
"numbers" => [0.1, 0.2, 0.5, 1, 2, 5],
"string_array" => ["all", "strings", "are the same", "type"]
}}
まとめ
- ElixirでTOML v1.0.0を使うにはtomerlを使う
- TOML v0.5.0でも良いなら、toml(Elixir)の選択肢もある
Discussion