Last active
January 17, 2022 09:46
-
-
Save benley/4fe6d2d354c3ac004de82ab51499eccb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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
I don't know TOML very well but this LGTM and I'd like to include it in the stdlib when you're ready.