From f2c0348bd3315d928aa6d6548a5c8452f4040a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Sat, 24 Jan 2026 23:39:01 +0100 Subject: [PATCH 1/4] Add TOML file parsing functionality to ConfigurationFile --- go.mod | 4 ++-- parser/parser.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 55510973..60d91f83 100644 --- a/go.mod +++ b/go.mod @@ -131,7 +131,7 @@ require ( github.com/nwaples/rardecode/v2 v2.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -161,7 +161,7 @@ require ( golang.org/x/mod v0.26.0 // indirect golang.org/x/net v0.42.0 // indirect golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect + golang.org/x/time v0.0.0-20220922220347-f3bd1da661af golang.org/x/tools v0.35.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect diff --git a/parser/parser.go b/parser/parser.go index 45aaa67f..19b9e57f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -14,6 +14,7 @@ import ( "github.com/goccy/go-json" "github.com/icza/dyno" "github.com/magiconair/properties" + "github.com/pelletier/go-toml/v2" "gopkg.in/ini.v1" "gopkg.in/yaml.v3" @@ -29,6 +30,7 @@ const ( Ini = "ini" Json = "json" Xml = "xml" + Toml = "toml" ) type ReplaceValue struct { @@ -227,6 +229,8 @@ func (f *ConfigurationFile) Parse(file ufs.File) error { err = f.parseIniFile(file) case Xml: err = f.parseXmlFile(file) + case Toml: + err = f.parseTomlFile(file) } return err } @@ -469,6 +473,49 @@ func (f *ConfigurationFile) parseYamlFile(file ufs.File) error { return nil } +// Parses a toml file and updates any matching key/value pairs before persisting +// it back to the disk. +func (f *ConfigurationFile) parseTomlFile(file ufs.File) error { + b, err := io.ReadAll(file) + if err != nil { + return err + } + + i := make(map[string]interface{}) + if err := toml.Unmarshal(b, &i); err != nil { + return err + } + + // Convert to JSON to reuse IterateOverJson for value replacement. + jsonBytes, err := json.Marshal(dyno.ConvertMapI2MapS(i)) + if err != nil { + return err + } + + data, err := f.IterateOverJson(jsonBytes) + if err != nil { + return err + } + + // Remarshal back to TOML format. + marshaled, err := toml.Marshal(data.Data()) + if err != nil { + return err + } + + if _, err := file.Seek(0, io.SeekStart); err != nil { + return err + } + if err := file.Truncate(0); err != nil { + return err + } + + if _, err := io.Copy(file, bytes.NewReader(marshaled)); err != nil { + return errors.Wrap(err, "parser: failed to write toml file to disk") + } + return nil +} + // Parses a text file using basic find and replace. This is a highly inefficient method of // scanning a file and performing a replacement. You should attempt to use anything other // than this function where possible. From 74c8a638ca28cdac43929ddfc9f87def4fac2c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Mon, 9 Feb 2026 23:25:10 +0100 Subject: [PATCH 2/4] Fix TOML parsing by unmarshalling JSON data before remarshal --- parser/parser.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/parser/parser.go b/parser/parser.go index 333556b8..25c7fcb1 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -508,8 +508,13 @@ func (f *ConfigurationFile) parseTomlFile(file ufs.File) error { return err } + var jsonData interface{} + if err := json.Unmarshal(data, &jsonData); err != nil { + return err + } + // Remarshal back to TOML format. - marshaled, err := toml.Marshal(data.Data()) + marshaled, err := toml.Marshal(jsonData) if err != nil { return err } From 777948d99e7d440b24f4189244244ef89e6c74e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Mon, 9 Feb 2026 23:31:39 +0100 Subject: [PATCH 3/4] Enhance TOML parsing by normalizing types and improving JSON decoding --- parser/parser.go | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/parser/parser.go b/parser/parser.go index 25c7fcb1..63b99375 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -6,6 +6,7 @@ import ( "io" "strconv" "strings" + "time" "emperror.dev/errors" "github.com/apex/log" @@ -461,9 +462,12 @@ func (f *ConfigurationFile) parseYamlFile(file ufs.File) error { } var jsonData interface{} - if err := json.Unmarshal(data, &jsonData); err != nil { + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.UseNumber() + if err := decoder.Decode(&jsonData); err != nil { return err } + jsonData = normalizeTomlTypes(jsonData) marshaled, err := yaml.Marshal(jsonData) if err != nil { @@ -532,6 +536,39 @@ func (f *ConfigurationFile) parseTomlFile(file ufs.File) error { return nil } +func normalizeTomlTypes(value interface{}) interface{} { + switch typed := value.(type) { + case map[string]interface{}: + for key, item := range typed { + typed[key] = normalizeTomlTypes(item) + } + return typed + case []interface{}: + for i := range typed { + typed[i] = normalizeTomlTypes(typed[i]) + } + return typed + case json.Number: + if intVal, err := typed.Int64(); err == nil { + return intVal + } + if floatVal, err := typed.Float64(); err == nil { + return floatVal + } + return typed.String() + case string: + if timeVal, err := time.Parse(time.RFC3339Nano, typed); err == nil { + return timeVal + } + if timeVal, err := time.Parse(time.RFC3339, typed); err == nil { + return timeVal + } + return typed + default: + return value + } +} + // Parses a text file using basic find and replace. This is a highly inefficient method of // scanning a file and performing a replacement. You should attempt to use anything other // than this function where possible. From de3b6c7590ce7df26791bea2653c0dd793ae872c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Mon, 9 Feb 2026 23:35:37 +0100 Subject: [PATCH 4/4] Refactor TOML parsing to use JSON decoder for improved type handling --- parser/parser.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 63b99375..a0482d86 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -462,12 +462,9 @@ func (f *ConfigurationFile) parseYamlFile(file ufs.File) error { } var jsonData interface{} - decoder := json.NewDecoder(bytes.NewReader(data)) - decoder.UseNumber() - if err := decoder.Decode(&jsonData); err != nil { + if err := json.Unmarshal(data, &jsonData); err != nil { return err } - jsonData = normalizeTomlTypes(jsonData) marshaled, err := yaml.Marshal(jsonData) if err != nil { @@ -513,9 +510,12 @@ func (f *ConfigurationFile) parseTomlFile(file ufs.File) error { } var jsonData interface{} - if err := json.Unmarshal(data, &jsonData); err != nil { + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.UseNumber() + if err := decoder.Decode(&jsonData); err != nil { return err } + jsonData = normalizeTomlTypes(jsonData) // Remarshal back to TOML format. marshaled, err := toml.Marshal(jsonData)