cfg/cfg.go

117 lines
2.4 KiB
Go

package cfg
import (
"encoding/json"
"fmt"
"strings"
"github.com/google/go-jsonnet"
"github.com/pelletier/go-toml/v2"
"github.com/philandstuff/dhall-golang/v6"
"github.com/sblinch/kdl-go"
"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"
JSONNET Encoding = "jsonnet"
YAML Encoding = "yaml"
TOML Encoding = "toml"
NIX Encoding = "nix"
DHALL Encoding = "dhall"
KDL Encoding = "kdl"
)
// 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 "jsonnet":
return JSONNET, nil
case "yaml":
return YAML, nil
case "toml":
return TOML, nil
case "nix":
return NIX, nil
case "dhall":
return DHALL, nil
case "kdl":
return KDL, 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:
if nixfig.Fmt != nil {
return nixfig.MarshalFormat(v)
}
return nixfig.Marshal(v)
case KDL:
return kdl.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 JSONNET:
vm := jsonnet.MakeVM()
data, err := vm.EvaluateAnonymousSnippet("cfg", string(data))
if err != nil {
return err
}
return json.Unmarshal([]byte(data), 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)
case KDL:
return kdl.Unmarshal(data, v)
default:
return fmt.Errorf("unknown unmarshal format %q", e)
}
}