aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/fromTOML.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/primops/fromTOML.cc')
-rw-r--r--src/libexpr/primops/fromTOML.cc111
1 files changed, 51 insertions, 60 deletions
diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc
index 4c6682dfd..bfea1ce34 100644
--- a/src/libexpr/primops/fromTOML.cc
+++ b/src/libexpr/primops/fromTOML.cc
@@ -1,86 +1,77 @@
#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;
+ std::function<void(Value &, toml::value)> visit;
- visit = [&](Value & v, std::shared_ptr<base> 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<toml::table>(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));
+ visit(v2, elem.second);
+ }
}
- 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]);
- }
-
- // 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]);
- }
+ 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<long>(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:
+ // We fail since Nix doesn't have date and time types
+ 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, "fromTOML" /* the "filename" */));
+ } catch (std::exception & e) { // TODO: toml::syntax_error
throw EvalError({
.msg = hintfmt("while parsing a TOML string: %s", e.what()),
.errPos = pos