github.com/octohelm/cuemod@v0.9.4/pkg/cueify/core/util.go (about)

     1  package core
     2  
     3  import (
     4  	encodingjson "encoding/json"
     5  	"reflect"
     6  	"sort"
     7  	"strconv"
     8  	"strings"
     9  	"unicode"
    10  
    11  	cueast "cuelang.org/go/cue/ast"
    12  	"cuelang.org/go/cue/literal"
    13  	cuetoken "cuelang.org/go/cue/token"
    14  	"cuelang.org/go/encoding/json"
    15  )
    16  
    17  func SafeIdentifierFromImportPath(s string) string {
    18  	parts := strings.Split(s, "/")
    19  
    20  	lastIdx := len(parts)
    21  
    22  	//
    23  	for {
    24  		lastIdx = lastIdx - 1
    25  
    26  		if lastIdx < 0 {
    27  			continue
    28  		}
    29  
    30  		last := parts[lastIdx]
    31  
    32  		// drop version in path
    33  		last = strings.Split(last, "@")[0]
    34  
    35  		// use parent when /v2
    36  		if len(last) > 2 && last[0] == 'v' {
    37  			// v2
    38  			if i, err := strconv.ParseInt(last[0:], 10, 64); err == nil && i > 1 {
    39  				continue
    40  			}
    41  		}
    42  
    43  		// use parent when number only
    44  		if len(last) > 0 && unicode.IsNumber(rune(last[0])) {
    45  			continue
    46  		}
    47  
    48  		runes := []rune(last)
    49  
    50  		for i, r := range runes {
    51  			if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '_' {
    52  				runes[i] = '_'
    53  			}
    54  		}
    55  
    56  		return string(runes)
    57  	}
    58  }
    59  
    60  func Extract(v interface{}) (cueast.Expr, error) {
    61  	data, err := encodingjson.Marshal(v)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	return json.Extract("", data)
    66  }
    67  
    68  func ExtractWithType(v interface{}) (cueast.Expr, error) {
    69  	switch x := v.(type) {
    70  	case map[string]interface{}:
    71  		if len(x) == 0 {
    72  			return cueast.NewStruct(&cueast.Field{
    73  				Label: cueast.NewList(cueast.NewIdent("string")),
    74  				Value: cueast.NewIdent("_"),
    75  			}), nil
    76  		}
    77  
    78  		keys := make([]string, 0)
    79  		for k := range x {
    80  			keys = append(keys, k)
    81  		}
    82  		sort.Strings(keys)
    83  
    84  		fields := make([]interface{}, len(keys))
    85  
    86  		for i, k := range keys {
    87  			valueExpr, err := ExtractWithType(x[k])
    88  			if err != nil {
    89  				return nil, err
    90  			}
    91  			fields[i] = &cueast.Field{
    92  				Label:    cueast.NewString(k),
    93  				Token:    cuetoken.COLON,
    94  				Optional: cuetoken.Blank.Pos(),
    95  				Value:    valueExpr,
    96  			}
    97  		}
    98  
    99  		return cueast.NewStruct(fields...), nil
   100  	case []interface{}:
   101  		typ := cueast.Expr(cueast.NewIdent("_"))
   102  		if len(x) > 0 {
   103  			t, err := ExtractWithType(x[0])
   104  			if err != nil {
   105  				return nil, err
   106  			}
   107  			typ = t
   108  		}
   109  		return cueast.NewList(&cueast.Ellipsis{Type: typ}), nil
   110  	case nil:
   111  		return cueast.NewIdent("_"), nil
   112  	default:
   113  		d, _ := encodingjson.Marshal(v)
   114  		expr, err := json.Extract("", d)
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  		return defaultValueAndType(
   119  			expr,
   120  			cueast.NewIdent(reflect.TypeOf(v).String()),
   121  		), nil
   122  	}
   123  }
   124  
   125  func defaultValueAndType(defaultValue cueast.Expr, t cueast.Expr) cueast.Expr {
   126  	return cueast.NewBinExpr(cuetoken.OR, &cueast.UnaryExpr{Op: cuetoken.MUL, X: defaultValue}, t)
   127  }
   128  
   129  func NewTripleBytes(data []byte) *cueast.BasicLit {
   130  	return &cueast.BasicLit{
   131  		Kind:     cuetoken.STRING,
   132  		ValuePos: cuetoken.NoPos,
   133  		Value:    "'''\n" + strings.Replace(string(data), "\\", "\\\\", -1) + "'''",
   134  	}
   135  }
   136  
   137  func NewBytes(data []byte) *cueast.BasicLit {
   138  	return &cueast.BasicLit{
   139  		Kind:     cuetoken.STRING,
   140  		ValuePos: cuetoken.NoPos,
   141  		Value:    literal.Bytes.Quote(string(data)),
   142  	}
   143  }