Skip to content

Instantly share code, notes, and snippets.

@ekimekim
Forked from benley/manifestToml.jsonnet
Last active February 21, 2018 21:50
Show Gist options
  • Save ekimekim/90e9ab41925c9c36788bd11348c78131 to your computer and use it in GitHub Desktop.
Save ekimekim/90e9ab41925c9c36788bd11348c78131 to your computer and use it in GitHub Desktop.
// Render any jsonnet value (except functions) to TOML format.
local
inlineTable(body) =
"{" +
std.join(", ", ["%s = %s" % [escapeKeyToml(k), renderBody(body[k])] for k in std.objectFields(body)]) +
"}",
renderArray(body) =
local
types = std.set([std.type(x) for x in body]),
// If any of the values are non-integer, we need to force all values to be rendered as floats.
forceFloat = std.foldl(function(result, item) result || (std.floor(item) != item), body, false);
if std.length(types) > 1
then error "TOML Arrays must be uniform-type. Multiple types found: %s" % std.join(", ", types)
else "[" + std.join(", ", [renderBody(x, forceFloat=forceFloat) for x in body]) + "]",
renderBody(body, forceFloat=false) =
if std.type(body) == "object" then inlineTable(body) else
if std.type(body) == "array" then renderArray(body) else
if std.type(body) == "number" && forceFloat then "%f" % body else
if std.type(body) == "number" then body else
if std.type(body) == "string" then escapeStringToml(body) else
if std.type(body) == "boolean" then body else
error "unsupported value for toml: got %s" % std.type(body),
renderItem(k, v) =
["%s = %s" % [escapeKeyToml(k), renderBody(v)]],
renderSection(path, v) =
["[%s]" % std.join(".", std.map(escapeKeyToml, path))] + topTable(v, path=path),
topTable(body, path=[]) =
local
nonObjects = std.flattenArrays([renderItem(k, body[k]) for k in std.objectFields(body) if std.type(body[k]) != "object"]),
objects = std.flattenArrays([renderSection(path + [k], body[k]) for k in std.objectFields(body) if std.type(body[k]) == "object"]),
hasBoth = std.length(nonObjects) > 0 && std.length(objects) > 0;
nonObjects
+ (if hasBoth then [""] else [])
+ objects,
escapeKeyToml(str) =
local bare_allowed = std.set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-");
if std.setUnion(std.set(str), bare_allowed) == bare_allowed then str else "%s" % escapeStringToml(str),
// JSON string encoding rules are a superset of TOML's - ie. all valid JSON strings are valid TOML strings
// but not vice versa (specifically, TOML only requires escaping control chars U+000, U+001f and U+007f,
// whereas JSON does not allow any control chars). Allowed escapes are the same.
escapeStringToml = std.escapeStringJson;
function(body)
if std.type(body) != "object"
then error "TOML body must be an object. Got %s" % std.type(body)
else std.lines(topTable(body))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment