1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
  | 
diff --git a/cfg.go b/cfg.go
new file mode 100644
index 0000000000000000000000000000000000000000..c3d9612364a3f0ce2be9fc02ea1967631c588bf8
--- /dev/null
+++ b/cfg.go
@@ -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)
+
+	}
+}
  |