diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2018-07-03T16·15+0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2018-07-03T16·39+0200 |
commit | 3b1f54cf06b6127a14479d18db8f08dc4c05d57a (patch) | |
tree | de6b77ac069b28b6af3d74ab0104518a7a1839d4 /src/libexpr | |
parent | a92ed973e569324b55cddb128f6f638f3ea1985c (diff) |
Add a fromTOML primop
This is primarily useful for processing Cargo.lock files.
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/primops/fromTOML.cc | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc new file mode 100644 index 000000000000..b04d7c407109 --- /dev/null +++ b/src/libexpr/primops/fromTOML.cc @@ -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); + +} |