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  }