package cfg import ( "encoding/json" "fmt" "strings" "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" 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 "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: 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 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) } }