mirror of https://git.jolheiser.com/cfg.git
feat: refactor for library and add test
Signed-off-by: jolheiser <john.olheiser@gmail.com>main
parent
b939bb8cfe
commit
b4097abed2
|
@ -0,0 +1,94 @@
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
"github.com/philandstuff/dhall-golang/v6"
|
||||||
|
"github.com/tailscale/hujson"
|
||||||
|
"go.jolheiser.com/nixfig"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encoding is a type of configuration encoding
|
||||||
|
type Encoding string
|
||||||
|
|
||||||
|
const (
|
||||||
|
JSON Encoding = "json"
|
||||||
|
JSONC Encoding = "jsonc"
|
||||||
|
YAML Encoding = "yaml"
|
||||||
|
TOML Encoding = "toml"
|
||||||
|
NIX Encoding = "nix"
|
||||||
|
DHALL Encoding = "dhall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Marshal takes data and encodes for an [Encoding]
|
||||||
|
func (e Encoding) Marshal(v any) ([]byte, error) {
|
||||||
|
return Marshal(e, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal decodes data for an [Encoding]
|
||||||
|
func (e Encoding) Unmarshal(data []byte, v any) error {
|
||||||
|
return Unmarshal(e, data, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEncoding parses a string into an [Encoding]
|
||||||
|
func ParseEncoding(s string) (Encoding, error) {
|
||||||
|
switch strings.ToLower(s) {
|
||||||
|
case "json":
|
||||||
|
return JSON, nil
|
||||||
|
case "jsonc":
|
||||||
|
return JSONC, nil
|
||||||
|
case "yaml":
|
||||||
|
return YAML, nil
|
||||||
|
case "toml":
|
||||||
|
return TOML, nil
|
||||||
|
case "nix":
|
||||||
|
return NIX, nil
|
||||||
|
case "dhall":
|
||||||
|
return DHALL, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unknown encoding %q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal is a top-level helper for encoding data
|
||||||
|
func Marshal(e Encoding, v any) ([]byte, error) {
|
||||||
|
switch e {
|
||||||
|
case JSON, JSONC:
|
||||||
|
return json.MarshalIndent(v, "", "\t")
|
||||||
|
case YAML:
|
||||||
|
return yaml.Marshal(v)
|
||||||
|
case TOML:
|
||||||
|
return toml.Marshal(v)
|
||||||
|
case NIX:
|
||||||
|
return nixfig.Marshal(v)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown marshal format %q", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal is a top-level helper for decoding data
|
||||||
|
func Unmarshal(e Encoding, data []byte, v any) error {
|
||||||
|
switch e {
|
||||||
|
case JSON, JSONC:
|
||||||
|
b, err := hujson.Standardize(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.Unmarshal(b, v)
|
||||||
|
case YAML:
|
||||||
|
return yaml.Unmarshal(data, v)
|
||||||
|
case TOML:
|
||||||
|
return toml.Unmarshal(data, v)
|
||||||
|
case NIX:
|
||||||
|
return nixfig.Unmarshal(data, v)
|
||||||
|
case DHALL:
|
||||||
|
return dhall.Unmarshal(data, v)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown unmarshal format %q", e)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/matryer/is"
|
||||||
|
"go.jolheiser.com/nixfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestData struct {
|
||||||
|
Foo string
|
||||||
|
Baz bool
|
||||||
|
Bux int
|
||||||
|
Qux TestSubData
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestSubData struct {
|
||||||
|
Honk string
|
||||||
|
Chonk int
|
||||||
|
Gonk bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncoding(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
|
||||||
|
// Starting with dhall since it can't be encoded
|
||||||
|
dhall := `
|
||||||
|
{
|
||||||
|
Foo = "bar"
|
||||||
|
, Baz = True
|
||||||
|
, Bux = 10
|
||||||
|
, Qux = {
|
||||||
|
Honk = "bonk"
|
||||||
|
, Chonk = 50
|
||||||
|
, Gonk = False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
final := TestData{
|
||||||
|
Foo: "bar",
|
||||||
|
Baz: true,
|
||||||
|
Bux: 10,
|
||||||
|
Qux: TestSubData{
|
||||||
|
Honk: "bonk",
|
||||||
|
Chonk: 50,
|
||||||
|
Gonk: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
encoders := []Encoding{JSON, JSONC, YAML, TOML}
|
||||||
|
// Only test nix if it's available
|
||||||
|
if nixfig.Nix != "" {
|
||||||
|
encoders = append(encoders, NIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data TestData
|
||||||
|
err := DHALL.Unmarshal([]byte(dhall), &data)
|
||||||
|
assert.NoErr(err) // Should be able to unmarshal dhall
|
||||||
|
|
||||||
|
for _, e := range encoders {
|
||||||
|
out, err := e.Marshal(data)
|
||||||
|
assert.NoErr(err) // Should be able to marshal
|
||||||
|
err = e.Unmarshal(out, &data)
|
||||||
|
assert.NoErr(err) // Should be able to unmarshal
|
||||||
|
}
|
||||||
|
assert.Equal(data, final) // Final structs should be equal
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -9,11 +8,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml/v2"
|
"go.jolheiser.com/cfg"
|
||||||
"github.com/philandstuff/dhall-golang/v6"
|
|
||||||
"github.com/tailscale/hujson"
|
|
||||||
"go.jolheiser.com/nixfig"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func maine() error {
|
func maine() error {
|
||||||
|
@ -22,45 +17,21 @@ func maine() error {
|
||||||
|
|
||||||
fs := flag.NewFlagSet("cfg", flag.ExitOnError)
|
fs := flag.NewFlagSet("cfg", flag.ExitOnError)
|
||||||
fromFunc := func(s string) error {
|
fromFunc := func(s string) error {
|
||||||
switch strings.ToLower(s) {
|
e, err := cfg.ParseEncoding(s)
|
||||||
case "json", "jsonc":
|
|
||||||
unmarshal = func(b []byte, a any) error {
|
|
||||||
b, err := hujson.Standardize(b)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return json.Unmarshal(b, a)
|
unmarshal = e.Unmarshal
|
||||||
}
|
|
||||||
case "yaml":
|
|
||||||
unmarshal = yaml.Unmarshal
|
|
||||||
case "toml":
|
|
||||||
unmarshal = toml.Unmarshal
|
|
||||||
case "dhall":
|
|
||||||
unmarshal = dhall.Unmarshal
|
|
||||||
case "nix":
|
|
||||||
unmarshal = nixfig.Unmarshal
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unknown format %q", s)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fs.Func("from", "The format to convert from", fromFunc)
|
fs.Func("from", "The format to convert from", fromFunc)
|
||||||
fs.Func("f", "--from", fromFunc)
|
fs.Func("f", "--from", fromFunc)
|
||||||
toFunc := func(s string) error {
|
toFunc := func(s string) error {
|
||||||
switch strings.ToLower(s) {
|
e, err := cfg.ParseEncoding(s)
|
||||||
case "json", "jsonc":
|
if err != nil {
|
||||||
marshal = func(a any) ([]byte, error) {
|
return err
|
||||||
return json.MarshalIndent(a, "", "\t")
|
|
||||||
}
|
|
||||||
case "yaml":
|
|
||||||
marshal = yaml.Marshal
|
|
||||||
case "toml":
|
|
||||||
marshal = toml.Marshal
|
|
||||||
case "nix":
|
|
||||||
marshal = nixfig.Marshal
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unknown format %q", s)
|
|
||||||
}
|
}
|
||||||
|
marshal = e.Marshal
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fs.Func("to", "The format to convert to", toFunc)
|
fs.Func("to", "The format to convert to", toFunc)
|
||||||
|
@ -95,7 +66,7 @@ func maine() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if marshal == nil {
|
} else if marshal == nil {
|
||||||
marshal = json.Marshal
|
marshal = cfg.JSON.Marshal
|
||||||
}
|
}
|
||||||
|
|
||||||
var data any
|
var data any
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module go.jolheiser.com/cfg
|
||||||
go 1.22.3
|
go 1.22.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/matryer/is v1.4.1
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2
|
github.com/pelletier/go-toml/v2 v2.2.2
|
||||||
github.com/philandstuff/dhall-golang/v6 v6.0.2
|
github.com/philandstuff/dhall-golang/v6 v6.0.2
|
||||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
|
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
|
||||||
|
@ -13,4 +14,6 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f // indirect
|
github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -25,6 +25,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406 h1:+OUpk+IVvmKU0jivOVFGtOzA6U5AWFs8HE4DRzWLOUE=
|
github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406 h1:+OUpk+IVvmKU0jivOVFGtOzA6U5AWFs8HE4DRzWLOUE=
|
||||||
github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
|
github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
|
||||||
|
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
|
||||||
|
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
@ -64,10 +66,12 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
Loading…
Reference in New Issue