github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/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/v5" 9 "github.com/v2fly/v2ray-core/v5/common/errors" 10 json_reader "github.com/v2fly/v2ray-core/v5/infra/conf/json" 11 v4 "github.com/v2fly/v2ray-core/v5/infra/conf/v4" 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) (*v4.Config, error) { 44 jsonConfig := &v4.Config{} 45 err := DecodeJSON(reader, jsonConfig) 46 if err != nil { 47 return nil, err 48 } 49 return jsonConfig, nil 50 } 51 52 // DecodeJSON reads from reader and decode into target 53 // syntax error could be detected. 54 func DecodeJSON(reader io.Reader, target interface{}) error { 55 jsonContent := bytes.NewBuffer(make([]byte, 0, 10240)) 56 jsonReader := io.TeeReader(&json_reader.Reader{ 57 Reader: reader, 58 }, jsonContent) 59 decoder := json.NewDecoder(jsonReader) 60 61 if err := decoder.Decode(target); err != nil { 62 var pos *offset 63 cause := errors.Cause(err) 64 switch tErr := cause.(type) { 65 case *json.SyntaxError: 66 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 67 case *json.UnmarshalTypeError: 68 pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) 69 } 70 if pos != nil { 71 return newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err) 72 } 73 return newError("failed to read config file").Base(err) 74 } 75 76 return nil 77 } 78 79 func LoadJSONConfig(reader io.Reader) (*core.Config, error) { 80 jsonConfig, err := DecodeJSONConfig(reader) 81 if err != nil { 82 return nil, err 83 } 84 85 pbConfig, err := jsonConfig.Build() 86 if err != nil { 87 return nil, newError("failed to parse json config").Base(err) 88 } 89 90 return pbConfig, nil 91 }