diff options
-rw-r--r-- | src/libexpr/primops/fromTOML.cc | 113 |
1 files changed, 53 insertions, 60 deletions
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<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) { (void) i; 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); - } + std::function<void(Value &, toml::value)> visit; - v.attrs->sort(); - } + visit = [&](Value & v, toml::value t) { - else if (auto t2 = t->as_array()) { - size_t size = t2->get().size(); + switch(t.type()) + { + case toml::value_t::table: + { + auto table = toml::get<toml::table>(t); - state.mkList(v, size); + size_t size = 0; + for (auto & i : table) { (void) i; size++; } - for (size_t i = 0; i < size; ++i) - visit(*(v.listElems()[i] = state.allocValue()), t2->get()[i]); - } + state.mkAttrs(v, size); - // 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(); + for(auto & elem: table) { - state.mkList(v, size); + auto & v2 = *state.allocAttr(v, state.symbols.create(elem.first)); - for (size_t j = 0; j < size; ++j) - visit(*(v.listElems()[j] = state.allocValue()), t2->get()[j]); - } + // TODO: note about creating children here in old code + visit(v2, elem.second); + } + } + break;; + case toml::value_t::array: + { + auto array = toml::get<std::vector<toml::value>>(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<bool>(t)); + break;; + case toml::value_t::integer: + mkInt(v, toml::get<int>(t)); + break;; + case toml::value_t::floating: + mkFloat(v, toml::get<double>(t)); + break;; + case toml::value_t::string: + mkString(v, toml::get<std::string>(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;; - else if (t->is_value()) { - if (auto val = t->as<int64_t>()) - 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) { + 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 |