- commit
- d5a38e8a790d85c9b24b1b52af24cf013419da50
- parent
- 1a265de64e4e3c401a0b3237689f0460532dbfd0
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2025-04-27 08:47
post on TOML
Diffstat
| A | _content/posts/2025-04-27-toml/index.md | 140 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 files changed, 140 insertions, 0 deletions
diff --git a/_content/posts/2025-04-27-toml/index.md b/_content/posts/2025-04-27-toml/index.md
@@ -0,0 +1,140 @@
-1 1 ---
-1 2 title: Some thoughts on TOML
-1 3 date: 2025-04-27
-1 4 tags: [code]
-1 5 description: "I wonder if there is room in the world for a variant of TOML that allows to overwrite values"
-1 6 ---
-1 7
-1 8 I recently read some things that made me think about configuration files,
-1 9 namely [TOML](https://toml.io/).
-1 10
-1 11 ## Comparison to INI
-1 12
-1 13 The first text was [An INI critique of
-1 14 TOML](https://github.com/madmurphy/libconfini/wiki/An-INI-critique-of-TOML)
-1 15 which compares TOML (quite unfavourably) to INI. As a quick reminder, INI is a
-1 16 family of formats that have a set of sections with key-value pairs, like this:
-1 17
-1 18 ```ini
-1 19 [server1]
-1 20 hostname = foo
-1 21 cores = 16
-1 22 online = true
-1 23 tags = linux, europe
-1 24
-1 25 [server2]
-1 26 hostname = bar
-1 27 cores = 8
-1 28 online = false
-1 29 tags = bsd, asia
-1 30 ```
-1 31
-1 32 I think it is fair to say that TOML is a rather distant relative in the INI
-1 33 family. The main critique in the article seems to be that TOML has types,
-1 34 similar to JSON. With INI, it is typically the application and not the
-1 35 configuration file that says how a value should be interpreted. So `false`
-1 36 could be interpreted as a boolean, but also as a string, or a list with a
-1 37 single element. Based on that difference, the author has multiple complaints
-1 38 about TOML:
-1 39
-1 40 - Users must know the correct types for value
-1 41 - Users must use quotes around strings and square brackets around lists
-1 42 - Date-related types are bad for some reason
-1 43 - The application still has to interpret values for types that are not
-1 44 covered by this simple system, e.g. enums
-1 45
-1 46 While I understand the critique, I don't think it is all that strong. I believe
-1 47 it is actually a good thing that users can understand the type of values from
-1 48 reading the configuration file. I don't really mind the quotes, square
-1 49 brackets, and dates. And my experience with JSON has taught me that a few
-1 50 simple types can go a long way. On the other hand, my experience with INI has
-1 51 taught me that having to call the correct typed getter on each use of a config
-1 52 value can become tedious.
-1 53
-1 54 The proper way to handle this is to validate the configuration before using it.
-1 55 If any values have the wrong type (TOML) or cannot be interpreted as the
-1 56 correct type (INI), the application should exit with a descriptive error
-1 57 message.
-1 58
-1 59 ## Overwrites
-1 60
-1 61 The second text was the [UAPI Group Configuration Files
-1 62 Specification](https://uapi-group.org/specifications/specs/configuration_files_specification/).
-1 63 This one is less about the format of configuration files themselves, but about
-1 64 their location in a Linux system. Crucially, it defines the concept of
-1 65 drop-ins, these `*.d` folders that can contain snippets of configuration
-1 66 that are combined together.
-1 67
-1 68 Combining multiple configuration files is important in two situations:
-1 69
-1 70 - You want to overwrite some specific values and otherwise use the defaults
-1 71 provided by the distro or vendor
-1 72 - Other packages should be able to add their own config, e.g. crontabs or
-1 73 apparmor profiles
-1 74
-1 75 The concept of drop-ins is well established. I am not convinced that it should
-1 76 be require for every single configuration file, but a lot of projects would
-1 77 benefit from it. So I was a bit surprised when I learned that TOML does not
-1 78 allow overwriting values. (I was also surprised that this limitation is not
-1 79 even mentioned in the INI article.) TOML is compatible with the second use case
-1 80 (adding new sections), but not with the first. And [that is not going to
-1 81 change](https://github.com/toml-lang/toml/issues/697).
-1 82
-1 83 Why is that and can it be fixed?
-1 84
-1 85 ## Hierarchy
-1 86
-1 87 INI doesn't have much of a hierarchy. There are sections, keys, and values, and
-1 88 that's it. TOML on the other hand interprets dots in sections and keys as
-1 89 additional levels of hierarchy:
-1 90
-1 91 ```toml
-1 92 [servers.foo]
-1 93 cores = 16
-1 94 status.online = true
-1 95 status.has_errors = false
-1 96 tags = ["linux", "europe"]
-1 97 ```
-1 98
-1 99 This also means that sections are basically just common prefixes and can be
-1 100 avoided entirely:
-1 101
-1 102 ```toml
-1 103 servers.foo.cores = 16
-1 104 servers.foo.status.online = true
-1 105 servers.foo.status.has_errors = false
-1 106 servers.foo.tags = ["linux", "europe"]
-1 107 ```
-1 108
-1 109 With this structure, overwriting would be simple: Later values simply overwrite
-1 110 earlier ones. However, the big issue are lists. How would you add, remove, or
-1 111 modify individual list items? For simple lists it might be ok to just replace
-1 112 them completely. But TOML provides not one but two ways to nest tables inside
-1 113 of lists:
-1 114
-1 115 ```
-1 116 # inline tables
-1 117 servers = [
-1 118 {hostname = "foo", cores = 16},
-1 119 {hostname = "bar", cores = 8},
-1 120 ]
-1 121
-1 122 # array of tables
-1 123 [[servers]]
-1 124 hostname = "foo"
-1 125 cores = 16
-1 126
-1 127 [[servers]]
-1 128 hostname = "bar"
-1 129 cores = 8
-1 130 ```
-1 131
-1 132 # Conclusion
-1 133
-1 134 Currently, we have the option to either not use TOML, not use overwrites, or
-1 135 merge the config after parsing (which might potentially lead to multiple,
-1 136 incompatible implementations).
-1 137
-1 138 I wonder if there is room in the world for a variant of TOML that allows
-1 139 to overwrite values and bans (or at least discourages) the use of tables inside
-1 140 of lists.