github.com/eagleql/xray-core@v1.4.4/infra/conf/serial/loader.go (about) 1 package serial 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "io/ioutil" 8 9 "github.com/ghodss/yaml" 10 "github.com/pelletier/go-toml" 11 12 "github.com/eagleql/xray-core/common/errors" 13 "github.com/eagleql/xray-core/core" 14 "github.com/eagleql/xray-core/infra/conf" 15 json_reader "github.com/eagleql/xray-core/infra/conf/json" 16 ) 17 18 type offset struct { 19 line int 20 char int 21 } 22 23 func findOffset(b []byte, o int) *offset { 24 if o >= len(b) || o < 0 { 25 return nil 26 } 27 28 line := 1 29 char := 0 30 for i, x := range b { 31 if i == o { 32 break 33 } 34 if x == '\n' { 35 line++ 36 char = 0 37 } else { 38 char++ 39 } 40 } 41 42 return &offset{line: line, char: char} 43 } 44 45 // DecodeJSONConfig reads from reader and decode the config into *conf.Config 46 // syntax error could be detected. 47 func DecodeJSONConfig(reader io.Reader) (*conf.Config, error) { 48 jsonConfig := &conf.Config{} 49 50 jsonContent := bytes.NewBuffer(make([]byte, 0, 10240)) 51 jsonReader := io.TeeReader(&json_reader.Reader{ 52 Reader: reader, 53 }, jsonContent) 54 decoder := json.NewDecoder(jsonReader) 55 56 if err := decoder.Decode(jsonConfig); err != nil { 57 var pos *offset 58 cause := errors.Cause(err) 59 switch tErr := cause.(type) { 60 case *json.SyntaxError: 61 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 62 case *json.UnmarshalTypeError: 63 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 64 } 65 if pos != nil { 66 return nil, newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err) 67 } 68 return nil, newError("failed to read config file").Base(err) 69 } 70 71 return jsonConfig, nil 72 } 73 74 func LoadJSONConfig(reader io.Reader) (*core.Config, error) { 75 jsonConfig, err := DecodeJSONConfig(reader) 76 if err != nil { 77 return nil, err 78 } 79 80 pbConfig, err := jsonConfig.Build() 81 if err != nil { 82 return nil, newError("failed to parse json config").Base(err) 83 } 84 85 return pbConfig, nil 86 } 87 88 // DecodeTOMLConfig reads from reader and decode the config into *conf.Config 89 // using github.com/pelletier/go-toml and map to convert toml to json. 90 func DecodeTOMLConfig(reader io.Reader) (*conf.Config, error) { 91 tomlFile, err := ioutil.ReadAll(reader) 92 if err != nil { 93 return nil, newError("failed to read config file").Base(err) 94 } 95 96 configMap := make(map[string]interface{}) 97 if err := toml.Unmarshal(tomlFile, &configMap); err != nil { 98 return nil, newError("failed to convert toml to map").Base(err) 99 } 100 101 jsonFile, err := json.Marshal(&configMap) 102 if err != nil { 103 return nil, newError("failed to convert map to json").Base(err) 104 } 105 106 return DecodeJSONConfig(bytes.NewReader(jsonFile)) 107 } 108 109 func LoadTOMLConfig(reader io.Reader) (*core.Config, error) { 110 tomlConfig, err := DecodeTOMLConfig(reader) 111 if err != nil { 112 return nil, err 113 } 114 115 pbConfig, err := tomlConfig.Build() 116 if err != nil { 117 return nil, newError("failed to parse toml config").Base(err) 118 } 119 120 return pbConfig, nil 121 } 122 123 // DecodeYAMLConfig reads from reader and decode the config into *conf.Config 124 // using github.com/ghodss/yaml to convert yaml to json. 125 func DecodeYAMLConfig(reader io.Reader) (*conf.Config, error) { 126 yamlFile, err := ioutil.ReadAll(reader) 127 if err != nil { 128 return nil, newError("failed to read config file").Base(err) 129 } 130 131 jsonFile, err := yaml.YAMLToJSON(yamlFile) 132 if err != nil { 133 return nil, newError("failed to convert yaml to json").Base(err) 134 } 135 136 return DecodeJSONConfig(bytes.NewReader(jsonFile)) 137 } 138 139 func LoadYAMLConfig(reader io.Reader) (*core.Config, error) { 140 yamlConfig, err := DecodeYAMLConfig(reader) 141 if err != nil { 142 return nil, err 143 } 144 145 pbConfig, err := yamlConfig.Build() 146 if err != nil { 147 return nil, newError("failed to parse yaml config").Base(err) 148 } 149 150 return pbConfig, nil 151 }