Add a fromTOML primop
This is primarily useful for processing Cargo.lock files.
This commit is contained in:
parent
a92ed973e5
commit
3b1f54cf06
4 changed files with 280 additions and 0 deletions
|
@ -2,6 +2,23 @@
|
||||||
|
|
||||||
with pkgs;
|
with pkgs;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cpptoml = runCommand "cpptoml"
|
||||||
|
{ src = fetchFromGitHub {
|
||||||
|
owner = "skystrife";
|
||||||
|
repo = "cpptoml";
|
||||||
|
rev = "43d7d8e52de149fd84aedf7eb71814ff9e6b2f7e";
|
||||||
|
sha256 = "0gdxk1mj5hpj93df1kwfl903w06nihbb1ayr3x336775jm2d2cw6";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
''
|
||||||
|
mkdir -p $out/include
|
||||||
|
cp $src/include/cpptoml.h $out/include/
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
# Use "busybox-sandbox-shell" if present,
|
# Use "busybox-sandbox-shell" if present,
|
||||||
# if not (legacy) fallback and hope it's sufficient.
|
# if not (legacy) fallback and hope it's sufficient.
|
||||||
|
@ -52,6 +69,7 @@ rec {
|
||||||
bzip2 xz brotli
|
bzip2 xz brotli
|
||||||
openssl pkgconfig sqlite boehmgc
|
openssl pkgconfig sqlite boehmgc
|
||||||
boost
|
boost
|
||||||
|
cpptoml
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
git
|
git
|
||||||
|
|
77
src/libexpr/primops/fromTOML.cc
Normal file
77
src/libexpr/primops/fromTOML.cc
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "primops.hh"
|
||||||
|
#include "eval-inline.hh"
|
||||||
|
|
||||||
|
#include <cpptoml.h>
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
using namespace cpptoml;
|
||||||
|
|
||||||
|
auto toml = state.forceStringNoCtx(*args[0], pos);
|
||||||
|
|
||||||
|
std::istringstream tomlStream(toml);
|
||||||
|
|
||||||
|
std::function<void(Value &, std::shared_ptr<base>)> visit;
|
||||||
|
|
||||||
|
visit = [&](Value & v, std::shared_ptr<base> t) {
|
||||||
|
|
||||||
|
if (auto t2 = t->as_table()) {
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
for (auto & i : *t2) size++;
|
||||||
|
|
||||||
|
state.mkAttrs(v, size);
|
||||||
|
|
||||||
|
for (auto & i : *t2) {
|
||||||
|
auto & v2 = *state.allocAttr(v, state.symbols.create(i.first));
|
||||||
|
|
||||||
|
if (auto i2 = i.second->as_table_array()) {
|
||||||
|
size_t size2 = i2->get().size();
|
||||||
|
state.mkList(v2, size2);
|
||||||
|
for (size_t j = 0; j < size2; ++j)
|
||||||
|
visit(*(v2.listElems()[j] = state.allocValue()), i2->get()[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
visit(v2, i.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.attrs->sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (auto t2 = t->as_array()) {
|
||||||
|
size_t size = t2->get().size();
|
||||||
|
|
||||||
|
state.mkList(v, size);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; ++i)
|
||||||
|
visit(*(v.listElems()[i] = state.allocValue()), t2->get()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (t->is_value()) {
|
||||||
|
if (auto val = t->as<NixInt>())
|
||||||
|
mkInt(v, val->get());
|
||||||
|
else if (auto val = t->as<NixFloat>())
|
||||||
|
mkFloat(v, val->get());
|
||||||
|
else if (auto val = t->as<bool>())
|
||||||
|
mkBool(v, val->get());
|
||||||
|
else if (auto val = t->as<std::string>())
|
||||||
|
mkString(v, val->get());
|
||||||
|
else
|
||||||
|
throw EvalError("unsupported value type in TOML");
|
||||||
|
}
|
||||||
|
|
||||||
|
else abort();
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
visit(v, parser(tomlStream).parse());
|
||||||
|
} catch (std::runtime_error & e) {
|
||||||
|
throw EvalError("while parsing a TOML string at %s: %s", pos, e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterPrimOp r("fromTOML", 1, prim_fromTOML);
|
||||||
|
|
||||||
|
}
|
1
tests/lang/eval-okay-fromTOML.exp
Normal file
1
tests/lang/eval-okay-fromTOML.exp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[ { clients = { data = [ [ "gamma" "delta" ] [ 1 2 ] ]; hosts = [ "alpha" "omega" ]; }; database = { connection_max = 5000; enabled = true; ports = [ 8001 8001 8002 ]; server = "192.168.1.1"; }; owner = { name = "Tom Preston-Werner"; }; servers = { alpha = { dc = "eqdc10"; ip = "10.0.0.1"; }; beta = { dc = "eqdc10"; ip = "10.0.0.2"; }; }; title = "TOML Example"; } { "'key2'" = "value"; "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; g = { h = { i = { }; }; }; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { "'l'" = { }; }; }; key = "value"; name = "Orange"; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } { metadata = { "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"; "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"; "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"; "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"; }; package = [ { dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "aho-corasick"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.6.4"; } { name = "ansi_term"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.9.0"; } { dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "atty"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.2.10"; } ]; } ]
|
184
tests/lang/eval-okay-fromTOML.nix
Normal file
184
tests/lang/eval-okay-fromTOML.nix
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
[
|
||||||
|
|
||||||
|
(builtins.fromTOML ''
|
||||||
|
# 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 = [ 8001, 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"
|
||||||
|
]
|
||||||
|
'')
|
||||||
|
|
||||||
|
(builtins.fromTOML ''
|
||||||
|
key = "value"
|
||||||
|
bare_key = "value"
|
||||||
|
bare-key = "value"
|
||||||
|
1234 = "value"
|
||||||
|
|
||||||
|
"127.0.0.1" = "value"
|
||||||
|
"character encoding" = "value"
|
||||||
|
"ʎǝʞ" = "value"
|
||||||
|
'key2' = "value"
|
||||||
|
#'quoted "value"' = "value"
|
||||||
|
|
||||||
|
name = "Orange"
|
||||||
|
|
||||||
|
# FIXME: cpptoml doesn't handle dotted keys properly yet.
|
||||||
|
#physical.color = "orange"
|
||||||
|
#physical.shape = "round"
|
||||||
|
#site."google.com" = true
|
||||||
|
|
||||||
|
#a.b.c = 1
|
||||||
|
#a.d = 2
|
||||||
|
|
||||||
|
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
|
||||||
|
|
||||||
|
int1 = +99
|
||||||
|
int2 = 42
|
||||||
|
int3 = 0
|
||||||
|
int4 = -17
|
||||||
|
int5 = 1_000
|
||||||
|
int6 = 5_349_221
|
||||||
|
int7 = 1_2_3_4_5
|
||||||
|
|
||||||
|
# FIXME: cpptoml doesn't support these yet:
|
||||||
|
|
||||||
|
#hex1 = 0xDEADBEEF
|
||||||
|
#hex2 = 0xdeadbeef
|
||||||
|
#hex3 = 0xdead_beef
|
||||||
|
|
||||||
|
#oct1 = 0o01234567
|
||||||
|
#oct2 = 0o755
|
||||||
|
|
||||||
|
#bin1 = 0b11010110
|
||||||
|
|
||||||
|
flt1 = +1.0
|
||||||
|
flt2 = 3.1415
|
||||||
|
flt3 = -0.01
|
||||||
|
flt4 = 5e+22
|
||||||
|
flt5 = 1e6
|
||||||
|
flt6 = -2E-2
|
||||||
|
flt7 = 6.626e-34
|
||||||
|
flt8 = 9_224_617.445_991_228_313
|
||||||
|
|
||||||
|
bool1 = true
|
||||||
|
bool2 = false
|
||||||
|
|
||||||
|
# FIXME: not supported because Nix doesn't have a date/time type.
|
||||||
|
#odt1 = 1979-05-27T07:32:00Z
|
||||||
|
#odt2 = 1979-05-27T00:32:00-07:00
|
||||||
|
#odt3 = 1979-05-27T00:32:00.999999-07:00
|
||||||
|
#odt4 = 1979-05-27 07:32:00Z
|
||||||
|
#ldt1 = 1979-05-27T07:32:00
|
||||||
|
#ldt2 = 1979-05-27T00:32:00.999999
|
||||||
|
#ld1 = 1979-05-27
|
||||||
|
#lt1 = 07:32:00
|
||||||
|
#lt2 = 00:32:00.999999
|
||||||
|
|
||||||
|
arr1 = [ 1, 2, 3 ]
|
||||||
|
arr2 = [ "red", "yellow", "green" ]
|
||||||
|
arr3 = [ [ 1, 2 ], [3, 4, 5] ]
|
||||||
|
arr4 = [ "all", 'strings', """are the same""", ''''type'''']
|
||||||
|
arr5 = [ [ 1, 2 ], ["a", "b", "c"] ]
|
||||||
|
|
||||||
|
arr7 = [
|
||||||
|
1, 2, 3
|
||||||
|
]
|
||||||
|
|
||||||
|
arr8 = [
|
||||||
|
1,
|
||||||
|
2, # this is ok
|
||||||
|
]
|
||||||
|
|
||||||
|
[table-1]
|
||||||
|
key1 = "some string"
|
||||||
|
key2 = 123
|
||||||
|
|
||||||
|
|
||||||
|
[table-2]
|
||||||
|
key1 = "another string"
|
||||||
|
key2 = 456
|
||||||
|
|
||||||
|
#[dog."tater.man"]
|
||||||
|
#type.name = "pug"
|
||||||
|
|
||||||
|
[a.b.c]
|
||||||
|
[ d.e.f ]
|
||||||
|
[ g . h . i ]
|
||||||
|
[ j . "ʞ" . 'l' ]
|
||||||
|
[x.y.z.w]
|
||||||
|
|
||||||
|
name = { first = "Tom", last = "Preston-Werner" }
|
||||||
|
point = { x = 1, y = 2 }
|
||||||
|
#animal = { type.name = "pug" }
|
||||||
|
|
||||||
|
[[products]]
|
||||||
|
name = "Hammer"
|
||||||
|
sku = 738594937
|
||||||
|
|
||||||
|
[[products]]
|
||||||
|
|
||||||
|
[[products]]
|
||||||
|
name = "Nail"
|
||||||
|
sku = 284758393
|
||||||
|
color = "gray"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(builtins.fromTOML ''
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||||
|
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||||
|
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||||
|
'')
|
||||||
|
]
|
Loading…
Reference in a new issue