Tags: #go #serialization
The following files demonstrate how the CLI will handle the input toml.
Here are the files:
example.toml: it represents similar content to what fastly.toml holds and we expect the CLI to manage.main.go: a reduced test case go program that attempts to decode/encode the provided toml to see how it handles things by default.output: shows the output of the go program.The TOML library will continue to produce more verbose output, and will overwrite the users toml with the verbose variation (only for fastly.toml, as that’s the only file that CLI manages).
I’ve written a custom marshaller but there are some issues to keep in mind.
First, here’s the implementation of the custom marshal:
func (m Manifest) MarshalTOML() ([]byte, error) {
var b bytes.Buffer
b.WriteString("managed = " + m.Managed + "\n\n")
b.WriteString("[testing.backends]\n")
for k, v := range m.Testing.Backends {
line := fmt.Sprintf("%s = { url = \"%s\" }\n", k, v.URL)
b.WriteString(line)
}
return b.Bytes(), nil
}
Here are the issues:
MarshalTOML.fastly.toml and their environment files. Meaning: there will be a difference between the fastly.toml (which the CLI will overwrite the toml with more verbose toml syntax) and the environment files that the CLI doesn’t manage.managed = "by CLI"
[testing.backends]
foo = { url = "https://foo.com/"}
"bar.baz" = { url = "https://barbaz.com/"}
qux = { url = "https://qux.com/"}
package main
import (
"fmt"
"io"
"log"
"os"
"github.com/pelletier/go-toml"
)
func main() {
fpath := "example.toml"
// NOTE: trying both Decode/Encode and Unmarshal/Marshal to see if there were any differences (there aren't).
md := decode(fpath)
toml.NewEncoder(os.Stdout).Encode(md)
mu := unmarshal(fpath)
b, _ := toml.Marshal(mu)
fmt.Println(string(b))
}
func decode(fpath string) Manifest {
fmt.Println("\nDECODE")
var m Manifest
f, err := os.OpenFile(fpath, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
fmt.Println("decode: %w", err)
}
toml.NewDecoder(f).Decode(&m)
fmt.Printf("\n%+v\n\n", m)
return m
}
func unmarshal(fpath string) Manifest {
fmt.Println("\nUNMARSHAL")
var m Manifest
f, err := os.OpenFile(fpath, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
fmt.Println("unmarshal: %w", err)
}
b, err := io.ReadAll(f)
if err != nil {
log.Fatal(err)
}
toml.Unmarshal(b, &m)
fmt.Printf("\n%+v\n\n", m)
return m
}
type Manifest struct {
Managed string `toml:"managed"`
Testing Testing `toml:"testing"`
}
type Testing struct {
Backends map[string]Backend `toml:"backends"`
}
type Backend struct {
URL string `toml:"url"`
}
DECODE
{Managed:by CLI Testing:{Backends:map[bar.baz:{URL:https://barbaz.com/} foo:{URL:https://foo.com/} qux:{URL:https://qux.com/}]}}
managed = "by CLI"
[testing]
[testing.backends]
[testing.backends."bar.baz"]
url = "https://barbaz.com/"
[testing.backends.foo]
url = "https://foo.com/"
[testing.backends.qux]
url = "https://qux.com/"
UNMARSHAL
{Managed:by CLI Testing:{Backends:map[bar.baz:{URL:https://barbaz.com/} foo:{URL:https://foo.com/} qux:{URL:https://qux.com/}]}}
managed = "by CLI"
[testing]
[testing.backends]
[testing.backends."bar.baz"]
url = "https://barbaz.com/"
[testing.backends.foo]
url = "https://foo.com/"
[testing.backends.qux]
url = "https://qux.com/"