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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
@ -9,11 +8,7 @@ import (
|
|||
"path/filepath"
|
||||
"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"
|
||||
"go.jolheiser.com/cfg"
|
||||
)
|
||||
|
||||
func maine() error {
|
||||
|
@ -22,45 +17,21 @@ func maine() error {
|
|||
|
||||
fs := flag.NewFlagSet("cfg", flag.ExitOnError)
|
||||
fromFunc := func(s string) error {
|
||||
switch strings.ToLower(s) {
|
||||
case "json", "jsonc":
|
||||
unmarshal = func(b []byte, a any) error {
|
||||
b, err := hujson.Standardize(b)
|
||||
e, err := cfg.ParseEncoding(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(b, a)
|
||||
}
|
||||
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)
|
||||
}
|
||||
unmarshal = e.Unmarshal
|
||||
return nil
|
||||
}
|
||||
fs.Func("from", "The format to convert from", fromFunc)
|
||||
fs.Func("f", "--from", fromFunc)
|
||||
toFunc := func(s string) error {
|
||||
switch strings.ToLower(s) {
|
||||
case "json", "jsonc":
|
||||
marshal = func(a any) ([]byte, error) {
|
||||
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)
|
||||
e, err := cfg.ParseEncoding(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
marshal = e.Marshal
|
||||
return nil
|
||||
}
|
||||
fs.Func("to", "The format to convert to", toFunc)
|
||||
|
@ -95,7 +66,7 @@ func maine() error {
|
|||
}
|
||||
}
|
||||
} else if marshal == nil {
|
||||
marshal = json.Marshal
|
||||
marshal = cfg.JSON.Marshal
|
||||
}
|
||||
|
||||
var data any
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module go.jolheiser.com/cfg
|
|||
go 1.22.3
|
||||
|
||||
require (
|
||||
github.com/matryer/is v1.4.1
|
||||
github.com/pelletier/go-toml/v2 v2.2.2
|
||||
github.com/philandstuff/dhall-golang/v6 v6.0.2
|
||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
|
||||
|
@ -13,4 +14,6 @@ require (
|
|||
require (
|
||||
github.com/fxamacker/cbor/v2 v2.2.1-0.20200511212021-28e39be4a84f // 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/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/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.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
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/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-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
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.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 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
Loading…
Reference in New Issue