mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-07-17 16:50:31 +00:00
Support array index notation in env var parsing
This commit is contained in:
parent
e3b16d5feb
commit
cbbca28a19
1 changed files with 67 additions and 2 deletions
|
|
@ -5,7 +5,9 @@ import (
|
||||||
"embed"
|
"embed"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/knadh/koanf/maps"
|
"github.com/knadh/koanf/maps"
|
||||||
"github.com/knadh/koanf/v2"
|
"github.com/knadh/koanf/v2"
|
||||||
|
|
@ -106,10 +108,73 @@ func (e *Env) Read() (Kv, error) {
|
||||||
key = strings.Replace(n[:x+1], "_", ".", -1) + n[x+2:]
|
key = strings.Replace(n[:x+1], "_", ".", -1) + n[x+2:]
|
||||||
}
|
}
|
||||||
if len(parts) > 1 {
|
if len(parts) > 1 {
|
||||||
mp[key] = parts[1]
|
mp[replaceArrayNotation(key)] = parts[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maps.Unflatten(mp, "."), nil
|
return arrayify(maps.Unflatten(mp, ".")).(Kv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaceArrayNotation converts array index notation like frames[0] into
|
||||||
|
// the delimiter-separated form frames.0. This allows maps.Unflatten to
|
||||||
|
// produce maps with numeric string keys, which are then converted to slices
|
||||||
|
// by arrayify.
|
||||||
|
func replaceArrayNotation(s string) string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.Grow(len(s))
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
c := s[i]
|
||||||
|
if c == '[' && i+1 < len(s) && unicode.IsDigit(rune(s[i+1])) {
|
||||||
|
b.WriteByte('.')
|
||||||
|
} else if c != ']' {
|
||||||
|
b.WriteByte(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrayify recursively walks a nested map and converts any
|
||||||
|
// map[string]any whose keys are all numeric strings into a []any.
|
||||||
|
func arrayify(v any) any {
|
||||||
|
switch val := v.(type) {
|
||||||
|
case map[string]any:
|
||||||
|
for k, sub := range val {
|
||||||
|
val[k] = arrayify(sub)
|
||||||
|
}
|
||||||
|
if isNumericMap(val) {
|
||||||
|
return mapToSlice(val)
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNumericMap(m map[string]any) bool {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for k := range m {
|
||||||
|
if _, err := strconv.Atoi(k); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToSlice(m map[string]any) []any {
|
||||||
|
max := 0
|
||||||
|
for k := range m {
|
||||||
|
n, _ := strconv.Atoi(k)
|
||||||
|
if n > max {
|
||||||
|
max = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out := make([]any, max+1)
|
||||||
|
for k, v := range m {
|
||||||
|
n, _ := strconv.Atoi(k)
|
||||||
|
out[n] = v
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads a configuration file into the given struct.
|
// LoadConfig loads a configuration file into the given struct.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue