github.com/v2fly/v2ray-core/v4@v4.45.2/infra/conf/serial/loader.go (about) 1 package serial 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 8 core "github.com/v2fly/v2ray-core/v4" 9 "github.com/v2fly/v2ray-core/v4/common/errors" 10 "github.com/v2fly/v2ray-core/v4/infra/conf" 11 json_reader "github.com/v2fly/v2ray-core/v4/infra/conf/json" 12 ) 13 14 type offset struct { 15 line int 16 char int 17 } 18 19 func findOffset(b []byte, o int) *offset { 20 if o >= len(b) || o < 0 { 21 return nil 22 } 23 24 line := 1 25 char := 0 26 for i, x := range b { 27 if i == o { 28 break 29 } 30 if x == '\n' { 31 line++ 32 char = 0 33 } else { 34 char++ 35 } 36 } 37 38 return &offset{line: line, char: char} 39 } 40 41 // DecodeJSONConfig reads from reader and decode the config into *conf.Config 42 // syntax error could be detected. 43 func DecodeJSONConfig(reader io.Reader) (*conf.Config, error) { 44 jsonConfig := &conf.Config{} 45 46 jsonContent := bytes.NewBuffer(make([]byte, 0, 10240)) 47 jsonReader := io.TeeReader(&json_reader.Reader{ 48 Reader: reader, 49 }, jsonContent) 50 decoder := json.NewDecoder(jsonReader) 51 52 if err := decoder.Decode(jsonConfig); err != nil { 53 var pos *offset 54 cause := errors.Cause(err) 55 switch tErr := cause.(type) { 56 case *json.SyntaxError: 57 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 58 case *json.UnmarshalTypeError: 59 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 60 } 61 if pos != nil { 62 return nil, newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err) 63 } 64 return nil, newError("failed to read config file").Base(err) 65 } 66 67 return jsonConfig, nil 68 } 69 70 func LoadJSONConfig(reader io.Reader) (*core.Config, error) { 71 jsonConfig, err := DecodeJSONConfig(reader) 72 if err != nil { 73 return nil, err 74 } 75 76 pbConfig, err := jsonConfig.Build() 77 if err != nil { 78 return nil, newError("failed to parse json config").Base(err) 79 } 80 81 return pbConfig, nil 82 }