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  }