loader.go 2.0 KB

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