github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/mergers/merger_base.go (about)

     1  package mergers
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/v2fly/v2ray-core/v5/common/cmdarg"
     8  	"github.com/v2fly/v2ray-core/v5/common/errors"
     9  	"github.com/v2fly/v2ray-core/v5/infra/conf/merge"
    10  )
    11  
    12  type jsonConverter func(v []byte) ([]byte, error)
    13  
    14  // makeMerger makes a merger who merge the format by converting it to JSON
    15  func makeMerger(name string, extensions []string, converter jsonConverter) *Merger {
    16  	return &Merger{
    17  		Name:       name,
    18  		Extensions: extensions,
    19  		Merge:      makeToJSONMergeFunc(converter),
    20  	}
    21  }
    22  
    23  // makeToJSONMergeFunc makes a merge func who merge the format by converting it to JSON
    24  func makeToJSONMergeFunc(converter func(v []byte) ([]byte, error)) MergeFunc {
    25  	return func(input interface{}, target map[string]interface{}) error {
    26  		if input == nil {
    27  			return nil
    28  		}
    29  		if target == nil {
    30  			return errors.New("merge target is nil")
    31  		}
    32  		switch v := input.(type) {
    33  		case string:
    34  			err := loadFile(v, target, converter)
    35  			if err != nil {
    36  				return err
    37  			}
    38  		case []string:
    39  			err := loadFiles(v, target, converter)
    40  			if err != nil {
    41  				return err
    42  			}
    43  		case cmdarg.Arg:
    44  			err := loadFiles(v, target, converter)
    45  			if err != nil {
    46  				return err
    47  			}
    48  		case []byte:
    49  			err := loadBytes(v, target, converter)
    50  			if err != nil {
    51  				return err
    52  			}
    53  		case io.Reader:
    54  			err := loadReader(v, target, converter)
    55  			if err != nil {
    56  				return err
    57  			}
    58  		default:
    59  			return newError("unknown merge input type")
    60  		}
    61  		return nil
    62  	}
    63  }
    64  
    65  func loadFiles(files []string, target map[string]interface{}, converter func(v []byte) ([]byte, error)) error {
    66  	for _, file := range files {
    67  		err := loadFile(file, target, converter)
    68  		if err != nil {
    69  			return err
    70  		}
    71  	}
    72  	return nil
    73  }
    74  
    75  func loadFile(file string, target map[string]interface{}, converter func(v []byte) ([]byte, error)) error {
    76  	bs, err := cmdarg.LoadArgToBytes(file)
    77  	if err != nil {
    78  		return fmt.Errorf("fail to load %s: %s", file, err)
    79  	}
    80  	if converter != nil {
    81  		bs, err = converter(bs)
    82  		if err != nil {
    83  			return fmt.Errorf("error convert to json '%s': %s", file, err)
    84  		}
    85  	}
    86  	_, err = merge.ToMap(bs, target)
    87  	return err
    88  }
    89  
    90  func loadReader(reader io.Reader, target map[string]interface{}, converter func(v []byte) ([]byte, error)) error {
    91  	bs, err := io.ReadAll(reader)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	return loadBytes(bs, target, converter)
    96  }
    97  
    98  func loadBytes(bs []byte, target map[string]interface{}, converter func(v []byte) ([]byte, error)) error {
    99  	var err error
   100  	if converter != nil {
   101  		bs, err = converter(bs)
   102  		if err != nil {
   103  			return fmt.Errorf("fail to convert to json: %s", err)
   104  		}
   105  	}
   106  	_, err = merge.ToMap(bs, target)
   107  	return err
   108  }