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 }