Hunter0x7c7
2022-08-11 b8230139fb40edea387617b6accd8371e37eda58
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
package loader
 
import (
    "encoding/json"
    "strings"
)
 
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
 
type ConfigCreator func() interface{}
 
type ConfigCreatorCache map[string]ConfigCreator
 
func (v ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
    if _, found := v[id]; found {
        return newError(id, " already registered.").AtError()
    }
 
    v[id] = creator
    return nil
}
 
func (v ConfigCreatorCache) CreateConfig(id string) (interface{}, error) {
    creator, found := v[id]
    if !found {
        return nil, newError("unknown config id: ", id)
    }
    return creator(), nil
}
 
type JSONConfigLoader struct {
    cache     ConfigCreatorCache
    idKey     string
    configKey string
}
 
func NewJSONConfigLoader(cache ConfigCreatorCache, idKey string, configKey string) *JSONConfigLoader {
    return &JSONConfigLoader{
        idKey:     idKey,
        configKey: configKey,
        cache:     cache,
    }
}
 
func (v *JSONConfigLoader) LoadWithID(raw []byte, id string) (interface{}, error) {
    id = strings.ToLower(id)
    config, err := v.cache.CreateConfig(id)
    if err != nil {
        return nil, err
    }
    if err := json.Unmarshal(raw, config); err != nil {
        return nil, err
    }
    return config, nil
}
 
func (v *JSONConfigLoader) Load(raw []byte) (interface{}, string, error) {
    var obj map[string]json.RawMessage
    if err := json.Unmarshal(raw, &obj); err != nil {
        return nil, "", err
    }
    rawID, found := obj[v.idKey]
    if !found {
        return nil, "", newError(v.idKey, " not found in JSON context").AtError()
    }
    var id string
    if err := json.Unmarshal(rawID, &id); err != nil {
        return nil, "", err
    }
    rawConfig := json.RawMessage(raw)
    if len(v.configKey) > 0 {
        configValue, found := obj[v.configKey]
        if found {
            rawConfig = configValue
        } else {
            // Default to empty json object.
            rawConfig = json.RawMessage([]byte("{}"))
        }
    }
    config, err := v.LoadWithID([]byte(rawConfig), id)
    if err != nil {
        return nil, id, err
    }
    return config, id, nil
}