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

     1  package mergers
     2  
     3  import (
     4  	"io"
     5  	"path/filepath"
     6  	"strings"
     7  
     8  	core "github.com/v2fly/v2ray-core/v5"
     9  	"github.com/v2fly/v2ray-core/v5/common/cmdarg"
    10  )
    11  
    12  // MergeAs load input and merge as specified format into m
    13  func MergeAs(formatName string, input interface{}, m map[string]interface{}) error {
    14  	f, found := mergersByName[formatName]
    15  	if !found {
    16  		return newError("format merger not found for: ", formatName)
    17  	}
    18  	return f.Merge(input, m)
    19  }
    20  
    21  // Merge loads inputs and merges them into m
    22  // it detects extension for merger selecting, or try all mergers
    23  // if no extension found
    24  func Merge(input interface{}, m map[string]interface{}) error {
    25  	if input == nil {
    26  		return nil
    27  	}
    28  	switch v := input.(type) {
    29  	case string:
    30  		err := mergeSingleFile(v, m)
    31  		if err != nil {
    32  			return err
    33  		}
    34  	case []string:
    35  		for _, file := range v {
    36  			err := mergeSingleFile(file, m)
    37  			if err != nil {
    38  				return err
    39  			}
    40  		}
    41  	case cmdarg.Arg:
    42  		for _, file := range v {
    43  			err := mergeSingleFile(file, m)
    44  			if err != nil {
    45  				return err
    46  			}
    47  		}
    48  	case []byte:
    49  		err := mergeSingleFile(v, m)
    50  		if err != nil {
    51  			return err
    52  		}
    53  	case io.Reader:
    54  		// read to []byte incase it tries different mergers
    55  		bs, err := io.ReadAll(v)
    56  		if err != nil {
    57  			return err
    58  		}
    59  		err = mergeSingleFile(bs, m)
    60  		if err != nil {
    61  			return err
    62  		}
    63  	default:
    64  		return newError("unknown merge input type")
    65  	}
    66  	return nil
    67  }
    68  
    69  func mergeSingleFile(input interface{}, m map[string]interface{}) error {
    70  	if file, ok := input.(string); ok {
    71  		ext := getExtension(file)
    72  		if ext != "" {
    73  			lext := strings.ToLower(ext)
    74  			f, found := mergersByExt[lext]
    75  			if !found {
    76  				return newError("unmergeable format extension: ", ext)
    77  			}
    78  			return f.Merge(file, m)
    79  		}
    80  	}
    81  	// no extension, try all mergers
    82  	for _, f := range mergersByName {
    83  		if f.Name == core.FormatAuto {
    84  			continue
    85  		}
    86  		err := f.Merge(input, m)
    87  		if err == nil {
    88  			return nil
    89  		}
    90  	}
    91  	return newError("tried all mergers but failed for: ", input).AtWarning()
    92  }
    93  
    94  func getExtension(filename string) string {
    95  	ext := filepath.Ext(filename)
    96  	return strings.ToLower(ext)
    97  }