From b13f0963f6203f0a9154ec21b0990651a7624878 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Sat, 1 Jan 2022 18:33:39 +0100 Subject: [PATCH] feat(encoding): experimental toml v2 support Signed-off-by: Mark Sagi-Kazar --- .github/workflows/ci.yml | 2 +- go.mod | 3 +- go.sum | 5 +- internal/encoding/toml/codec.go | 3 + internal/encoding/toml/codec2.go | 19 +++++ internal/encoding/toml/codec2_test.go | 109 ++++++++++++++++++++++++++ internal/encoding/toml/codec_test.go | 3 + 7 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 internal/encoding/toml/codec2.go create mode 100644 internal/encoding/toml/codec2_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b59d89..3feb2e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: matrix: os: [ubuntu-latest, macos-latest, windows-latest] go: ['1.14', '1.15', '1.16', '1.17'] - tags: ['', 'viper_yaml3'] + tags: ['', 'viper_yaml3', 'viper_toml2'] env: GOFLAGS: -mod=readonly diff --git a/go.mod b/go.mod index 608a0a6..a82456d 100644 --- a/go.mod +++ b/go.mod @@ -8,12 +8,13 @@ require ( github.com/magiconair/properties v1.8.5 github.com/mitchellh/mapstructure v1.4.3 github.com/pelletier/go-toml v1.9.4 + github.com/pelletier/go-toml/v2 v2.0.0-beta.6 github.com/sagikazarmark/crypt v0.4.0 github.com/spf13/afero v1.7.1 github.com/spf13/cast v1.4.1 github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 github.com/subosito/gotenv v1.2.0 gopkg.in/ini.v1 v1.66.2 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 7783177..2ec8b45 100644 --- a/go.sum +++ b/go.sum @@ -318,6 +318,8 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.0-beta.6 h1:JFNqj2afbbhCqTiyN16D7Tudc/aaDzE2FBDk+VlBQnE= +github.com/pelletier/go-toml/v2 v2.0.0-beta.6/go.mod h1:ke6xncR3W76Ba8xnVxkrZG0js6Rd2BsQEAYrfgJ6eQA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -368,8 +370,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 h1:t0lM6y/M5IiUZyvbBTcngso8SZEZICH7is9B6g/obVU= +github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= diff --git a/internal/encoding/toml/codec.go b/internal/encoding/toml/codec.go index ad0a18b..ff1112c 100644 --- a/internal/encoding/toml/codec.go +++ b/internal/encoding/toml/codec.go @@ -1,3 +1,6 @@ +//go:build !viper_toml2 +// +build !viper_toml2 + package toml import ( diff --git a/internal/encoding/toml/codec2.go b/internal/encoding/toml/codec2.go new file mode 100644 index 0000000..566b706 --- /dev/null +++ b/internal/encoding/toml/codec2.go @@ -0,0 +1,19 @@ +//go:build viper_toml2 +// +build viper_toml2 + +package toml + +import ( + "github.com/pelletier/go-toml/v2" +) + +// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding. +type Codec struct{} + +func (Codec) Encode(v map[string]interface{}) ([]byte, error) { + return toml.Marshal(v) +} + +func (Codec) Decode(b []byte, v map[string]interface{}) error { + return toml.Unmarshal(b, &v) +} diff --git a/internal/encoding/toml/codec2_test.go b/internal/encoding/toml/codec2_test.go new file mode 100644 index 0000000..271e321 --- /dev/null +++ b/internal/encoding/toml/codec2_test.go @@ -0,0 +1,109 @@ +//go:build viper_toml2 +// +build viper_toml2 + +package toml + +import ( + "reflect" + "testing" +) + +// original form of the data +const original = `# key-value pair +key = "value" +list = ["item1", "item2", "item3"] + +[map] +key = "value" + +# nested +# map +[nested_map] +[nested_map.map] +key = "value" +list = [ + "item1", + "item2", + "item3", +] +` + +// encoded form of the data +const encoded = `key = 'value' +list = ['item1', 'item2', 'item3'] +[map] +key = 'value' + +[nested_map] +[nested_map.map] +key = 'value' +list = ['item1', 'item2', 'item3'] + + +` + +// Viper's internal representation +var data = map[string]interface{}{ + "key": "value", + "list": []interface{}{ + "item1", + "item2", + "item3", + }, + "map": map[string]interface{}{ + "key": "value", + }, + "nested_map": map[string]interface{}{ + "map": map[string]interface{}{ + "key": "value", + "list": []interface{}{ + "item1", + "item2", + "item3", + }, + }, + }, +} + +func TestCodec_Encode(t *testing.T) { + codec := Codec{} + + b, err := codec.Encode(data) + if err != nil { + t.Fatal(err) + } + + if encoded != string(b) { + t.Fatalf("decoded value does not match the expected one\nactual: %#v\nexpected: %#v", string(b), encoded) + } +} + +func TestCodec_Decode(t *testing.T) { + t.Run("OK", func(t *testing.T) { + codec := Codec{} + + v := map[string]interface{}{} + + err := codec.Decode([]byte(original), v) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(data, v) { + t.Fatalf("decoded value does not match the expected one\nactual: %#v\nexpected: %#v", v, data) + } + }) + + t.Run("InvalidData", func(t *testing.T) { + codec := Codec{} + + v := map[string]interface{}{} + + err := codec.Decode([]byte(`invalid data`), v) + if err == nil { + t.Fatal("expected decoding to fail") + } + + t.Logf("decoding failed as expected: %s", err) + }) +} diff --git a/internal/encoding/toml/codec_test.go b/internal/encoding/toml/codec_test.go index 33435e6..c7a2756 100644 --- a/internal/encoding/toml/codec_test.go +++ b/internal/encoding/toml/codec_test.go @@ -1,3 +1,6 @@ +//go:build !viper_toml2 +// +build !viper_toml2 + package toml import (