Skip to content

Instantly share code, notes, and snippets.

@benley
Last active January 17, 2022 09:46
Show Gist options
  • Save benley/4fe6d2d354c3ac004de82ab51499eccb to your computer and use it in GitHub Desktop.
Save benley/4fe6d2d354c3ac004de82ab51499eccb 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))
@sparkprime
Copy link

I don't know TOML very well but this LGTM and I'd like to include it in the stdlib when you're ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment