diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index 4c6682dfd..8fba0bf04 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -1,86 +1,79 @@ #include "primops.hh" #include "eval-inline.hh" -#include "../../cpptoml/cpptoml.h" +#include "../../toml11/toml.hpp" namespace nix { -static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & v) +static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & val) { - using namespace cpptoml; - auto toml = state.forceStringNoCtx(*args[0], pos); std::istringstream tomlStream(toml); - std::function)> visit; + std::function visit; - visit = [&](Value & v, std::shared_ptr t) { + visit = [&](Value & v, toml::value t) { - if (auto t2 = t->as_table()) { + switch(t.type()) + { + case toml::value_t::table: + { + auto table = toml::get(t); - size_t size = 0; - for (auto & i : *t2) { (void) i; size++; } + size_t size = 0; + for (auto & i : table) { (void) i; size++; } - state.mkAttrs(v, size); + state.mkAttrs(v, size); - for (auto & i : *t2) { - auto & v2 = *state.allocAttr(v, state.symbols.create(i.first)); + for(auto & elem: table) { - 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]); + auto & v2 = *state.allocAttr(v, state.symbols.create(elem.first)); + + // TODO: note about creating children here in old code + visit(v2, elem.second); + } } - else - visit(v2, i.second); - } + break;; + case toml::value_t::array: + { + auto array = toml::get>(t); + + size_t size = array.size(); + state.mkList(v, size); + for (size_t i = 0; i < size; ++i) + visit(*(v.listElems()[i] = state.allocValue()), array[i]); + } + break;; + case toml::value_t::boolean: + mkBool(v, toml::get(t)); + break;; + case toml::value_t::integer: + mkInt(v, toml::get(t)); + break;; + case toml::value_t::floating: + mkFloat(v, toml::get(t)); + break;; + case toml::value_t::string: + mkString(v, toml::get(t)); + break;; + case toml::value_t::local_datetime: + case toml::value_t::offset_datetime: + case toml::value_t::local_date: + case toml::value_t::local_time: + // TODO: convert to string? + throw std::runtime_error("Dates and times are not supported"); + break;; + case toml::value_t::empty: + mkNull(v); + break;; - 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]); - } - - // Handle cases like 'a = [[{ a = true }]]', which IMHO should be - // parsed as a array containing an array containing a table, - // but instead are parsed as an array containing a table array - // containing a table. - else if (auto t2 = t->as_table_array()) { - size_t size = t2->get().size(); - - state.mkList(v, size); - - for (size_t j = 0; j < size; ++j) - visit(*(v.listElems()[j] = state.allocValue()), t2->get()[j]); - } - - else if (t->is_value()) { - if (auto val = t->as()) - mkInt(v, val->get()); - else if (auto val = t->as()) - mkFloat(v, val->get()); - else if (auto val = t->as()) - mkBool(v, val->get()); - else if (auto val = t->as()) - 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) { + visit(val, toml::parse(tomlStream)); // TODO give filename + } catch (std::exception & e) { // TODO: toml::syntax_error throw EvalError({ .msg = hintfmt("while parsing a TOML string: %s", e.what()), .errPos = pos