init
This commit is contained in:
83
config/parser.go
Normal file
83
config/parser.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Format represents a config file format.
|
||||
type Format int
|
||||
|
||||
const (
|
||||
FormatJSON Format = iota
|
||||
FormatYAML
|
||||
)
|
||||
|
||||
// DetectFormat returns the format based on file extension.
|
||||
func DetectFormat(path string) (Format, error) {
|
||||
ext := strings.ToLower(filepath.Ext(path))
|
||||
switch ext {
|
||||
case ".json":
|
||||
return FormatJSON, nil
|
||||
case ".yaml", ".yml":
|
||||
return FormatYAML, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported format: %s", ext)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse deserializes raw bytes into a map based on the given format.
|
||||
func Parse(data []byte, format Format) (map[string]any, error) {
|
||||
var result map[string]any
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON: %w", err)
|
||||
}
|
||||
case FormatYAML:
|
||||
if err := yaml.Unmarshal(data, &result); err != nil {
|
||||
return nil, fmt.Errorf("invalid YAML: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown format")
|
||||
}
|
||||
if result == nil {
|
||||
result = make(map[string]any)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Serialize converts a map back to bytes in the given format.
|
||||
func Serialize(data map[string]any, format Format) ([]byte, error) {
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
return json.MarshalIndent(data, "", " ")
|
||||
case FormatYAML:
|
||||
return yaml.Marshal(data)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown format")
|
||||
}
|
||||
}
|
||||
|
||||
// DeepMerge merges src into dst recursively. Values in src override those in dst.
|
||||
// Nested maps are merged; all other types are replaced.
|
||||
func DeepMerge(dst, src map[string]any) map[string]any {
|
||||
out := make(map[string]any, len(dst))
|
||||
for k, v := range dst {
|
||||
out[k] = v
|
||||
}
|
||||
for k, v := range src {
|
||||
if srcMap, ok := v.(map[string]any); ok {
|
||||
if dstMap, ok := out[k].(map[string]any); ok {
|
||||
out[k] = DeepMerge(dstMap, srcMap)
|
||||
continue
|
||||
}
|
||||
}
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user