Toml.Literal

Writing a value that was not read from a file.

Every node in the AST carries the text it was written as, which is what makes a document that came from a file go back byte for byte. A value a program has just made up has no such text yet, so something has to choose it, and this is where that choosing is done -- once, so that Toml.Edit and Toml.Encode cannot disagree about how to spell a float.

The choices are the plain ones: a bare key when the grammar allows and a quoted one when it does not, decimal for integers, and only the escapes a string actually needs.

Toml.Literal.string "10.0.0.1"      -- ip = "10.0.0.1"
Toml.Literal.int 8000               -- ports = [8000]
Toml.Literal.float 79.5             -- cpu = 79.5
Toml.Literal.bool True              -- enabled = true

Toml.Literal.array
    [ Toml.Literal.int 8000, Toml.Literal.int 8001, Toml.Literal.int 8002 ]
-- ports = [8000, 8001, 8002]

Toml.Literal.inlineTable
    [ { key = "cpu", value = Toml.Literal.float 79.5 }
    , { key = "case", value = Toml.Literal.float 72.0 }
    ]
-- temp_targets = { cpu = 79.5, case = 72.0 }

The one to read twice is float, because a Float and a decimal are not the same thing and this module has to pick one of them to write.

string : String -> Value

A string.

int : Int -> Value

An integer that fits in a Gren Int.

bigInt : BigInt -> Value

An integer of any size.

float : Float -> Value

A float.

inf and nan are written as those words. Everything else is written as the shortest decimal that reads back as the same Float, which is what String.fromFloat gives: 3.14 and not the fifty-one digits of the binary value that is nearest to it.

That is a choice, and it is the opposite of the one bigDecimal makes. A Float is the nearest double, so the exact expansion is not wrong -- but it is not what the caller meant either, and writing it into a config file would be a strange way to say 3.14. A caller who does mean the exact value has a BigDecimal and should say so.

Everything gets a decimal point even when it does not need one, because 1 without one is an integer in TOML and this function was asked for a float.

bigDecimal : BigDecimal -> Value

An exact decimal, written as it stands. Every digit of it, which is the whole reason for having one -- see float for the other choice.

bool : Bool -> Value

A boolean.

offsetDateTime : DateTime -> Value

A date and time with an offset. Fails over to a local date-time if the value has no offset, since that is what it is.

localDateTime : DateTime -> Value

A date and time with no offset.

localDate : Date -> Value

A date.

localTime : Time -> Value

A time of day.

array : Array Value -> Value

An array on one line: [1, 2, 3].

A space after each comma and none against the brackets, so an empty one is []. The elements are values, not fields, so an inline table inside an array is inlineTable -- there is no header to be had in there.

inlineTable : Array { key : String, value : Value } -> Value

An inline table on one line: { a = 1, b = 2 }.

A space inside each brace and one either side of every equals sign, except that an empty one is {} -- a space inside that would be an odd thing to write.

key : Array String -> Key

A whole key from its parts.

simpleKey : String -> SimpleKey

One part of a key, written bare when the grammar allows and quoted when it does not.

path : Key -> Array String

The parts of a key, as the table tree names them.