2018-07-03 19:15:59 +03:00
|
|
|
#include "primops.hh"
|
|
|
|
#include "eval-inline.hh"
|
|
|
|
|
2021-12-17 23:03:48 +02:00
|
|
|
#include "../../toml11/toml.hpp"
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2023-06-09 12:53:18 +03:00
|
|
|
#include <sstream>
|
|
|
|
|
2018-07-03 19:15:59 +03:00
|
|
|
namespace nix {
|
|
|
|
|
2022-03-04 20:31:59 +02:00
|
|
|
static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value & val)
|
2018-07-03 19:15:59 +03:00
|
|
|
{
|
2023-01-19 14:23:04 +02:00
|
|
|
auto toml = state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.fromTOML");
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2022-02-25 17:00:00 +02:00
|
|
|
std::istringstream tomlStream(std::string{toml});
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2021-12-17 23:03:48 +02:00
|
|
|
std::function<void(Value &, toml::value)> visit;
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2021-12-17 23:03:48 +02:00
|
|
|
visit = [&](Value & v, toml::value t) {
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2021-12-17 23:03:48 +02:00
|
|
|
switch(t.type())
|
|
|
|
{
|
|
|
|
case toml::value_t::table:
|
|
|
|
{
|
|
|
|
auto table = toml::get<toml::table>(t);
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2021-12-17 23:03:48 +02:00
|
|
|
size_t size = 0;
|
|
|
|
for (auto & i : table) { (void) i; size++; }
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2022-01-04 18:39:16 +02:00
|
|
|
auto attrs = state.buildBindings(size);
|
2018-07-03 19:15:59 +03:00
|
|
|
|
2022-01-04 18:39:16 +02:00
|
|
|
for(auto & elem : table)
|
|
|
|
visit(attrs.alloc(elem.first), elem.second);
|
2019-06-24 18:09:09 +03:00
|
|
|
|
2022-01-04 18:39:16 +02:00
|
|
|
v.mkAttrs(attrs);
|
2021-12-17 23:03:48 +02:00
|
|
|
}
|
|
|
|
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:
|
2022-01-04 19:40:39 +02:00
|
|
|
v.mkBool(toml::get<bool>(t));
|
2021-12-17 23:03:48 +02:00
|
|
|
break;;
|
|
|
|
case toml::value_t::integer:
|
2022-01-04 19:40:39 +02:00
|
|
|
v.mkInt(toml::get<int64_t>(t));
|
2021-12-17 23:03:48 +02:00
|
|
|
break;;
|
|
|
|
case toml::value_t::floating:
|
2022-01-04 19:40:39 +02:00
|
|
|
v.mkFloat(toml::get<NixFloat>(t));
|
2021-12-17 23:03:48 +02:00
|
|
|
break;;
|
|
|
|
case toml::value_t::string:
|
2022-01-04 19:24:42 +02:00
|
|
|
v.mkString(toml::get<std::string>(t));
|
2021-12-17 23:03:48 +02:00
|
|
|
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:
|
2023-06-09 12:53:18 +03:00
|
|
|
{
|
|
|
|
if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) {
|
|
|
|
auto attrs = state.buildBindings(2);
|
|
|
|
attrs.alloc("_type").mkString("timestamp");
|
|
|
|
std::ostringstream s;
|
|
|
|
s << t;
|
|
|
|
attrs.alloc("value").mkString(s.str());
|
|
|
|
v.mkAttrs(attrs);
|
|
|
|
} else {
|
|
|
|
throw std::runtime_error("Dates and times are not supported");
|
|
|
|
}
|
|
|
|
}
|
2021-12-17 23:03:48 +02:00
|
|
|
break;;
|
|
|
|
case toml::value_t::empty:
|
2022-01-04 19:40:39 +02:00
|
|
|
v.mkNull();
|
2021-12-17 23:03:48 +02:00
|
|
|
break;;
|
2019-06-24 18:09:09 +03:00
|
|
|
|
2018-07-03 19:15:59 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
2021-12-20 22:39:37 +02:00
|
|
|
visit(val, toml::parse(tomlStream, "fromTOML" /* the "filename" */));
|
2021-12-17 23:03:48 +02:00
|
|
|
} catch (std::exception & e) { // TODO: toml::syntax_error
|
2020-06-15 15:06:58 +03:00
|
|
|
throw EvalError({
|
2021-01-21 01:27:36 +02:00
|
|
|
.msg = hintfmt("while parsing a TOML string: %s", e.what()),
|
2022-03-04 20:31:59 +02:00
|
|
|
.errPos = state.positions[pos]
|
2020-06-15 15:06:58 +03:00
|
|
|
});
|
2018-07-03 19:15:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-11 17:57:50 +03:00
|
|
|
static RegisterPrimOp primop_fromTOML({
|
|
|
|
.name = "fromTOML",
|
|
|
|
.arity = 1,
|
|
|
|
.fun = prim_fromTOML
|
|
|
|
});
|
2018-07-03 19:15:59 +03:00
|
|
|
|
|
|
|
}
|