github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/helper/pluginutils/hclspecutils/type_expr.go (about) 1 package hclspecutils 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/hashicorp/hcl2/hcl" 8 "github.com/zclconf/go-cty/cty" 9 "github.com/zclconf/go-cty/cty/function" 10 ) 11 12 var typeType = cty.Capsule("type", reflect.TypeOf(cty.NilType)) 13 14 var typeEvalCtx = &hcl.EvalContext{ 15 Variables: map[string]cty.Value{ 16 "string": wrapTypeType(cty.String), 17 "bool": wrapTypeType(cty.Bool), 18 "number": wrapTypeType(cty.Number), 19 "any": wrapTypeType(cty.DynamicPseudoType), 20 }, 21 Functions: map[string]function.Function{ 22 "list": function.New(&function.Spec{ 23 Params: []function.Parameter{ 24 { 25 Name: "element_type", 26 Type: typeType, 27 }, 28 }, 29 Type: function.StaticReturnType(typeType), 30 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 31 ety := unwrapTypeType(args[0]) 32 ty := cty.List(ety) 33 return wrapTypeType(ty), nil 34 }, 35 }), 36 "set": function.New(&function.Spec{ 37 Params: []function.Parameter{ 38 { 39 Name: "element_type", 40 Type: typeType, 41 }, 42 }, 43 Type: function.StaticReturnType(typeType), 44 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 45 ety := unwrapTypeType(args[0]) 46 ty := cty.Set(ety) 47 return wrapTypeType(ty), nil 48 }, 49 }), 50 "map": function.New(&function.Spec{ 51 Params: []function.Parameter{ 52 { 53 Name: "element_type", 54 Type: typeType, 55 }, 56 }, 57 Type: function.StaticReturnType(typeType), 58 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 59 ety := unwrapTypeType(args[0]) 60 ty := cty.Map(ety) 61 return wrapTypeType(ty), nil 62 }, 63 }), 64 "tuple": function.New(&function.Spec{ 65 Params: []function.Parameter{ 66 { 67 Name: "element_types", 68 Type: cty.List(typeType), 69 }, 70 }, 71 Type: function.StaticReturnType(typeType), 72 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 73 etysVal := args[0] 74 etys := make([]cty.Type, 0, etysVal.LengthInt()) 75 for it := etysVal.ElementIterator(); it.Next(); { 76 _, wrapEty := it.Element() 77 etys = append(etys, unwrapTypeType(wrapEty)) 78 } 79 ty := cty.Tuple(etys) 80 return wrapTypeType(ty), nil 81 }, 82 }), 83 "object": function.New(&function.Spec{ 84 Params: []function.Parameter{ 85 { 86 Name: "attribute_types", 87 Type: cty.Map(typeType), 88 }, 89 }, 90 Type: function.StaticReturnType(typeType), 91 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 92 atysVal := args[0] 93 atys := make(map[string]cty.Type) 94 for it := atysVal.ElementIterator(); it.Next(); { 95 nameVal, wrapAty := it.Element() 96 name := nameVal.AsString() 97 atys[name] = unwrapTypeType(wrapAty) 98 } 99 ty := cty.Object(atys) 100 return wrapTypeType(ty), nil 101 }, 102 }), 103 }, 104 } 105 106 func evalTypeExpr(expr hcl.Expression) (cty.Type, hcl.Diagnostics) { 107 result, diags := expr.Value(typeEvalCtx) 108 if result.IsNull() { 109 return cty.DynamicPseudoType, diags 110 } 111 if !result.Type().Equals(typeType) { 112 diags = append(diags, &hcl.Diagnostic{ 113 Severity: hcl.DiagError, 114 Summary: "Invalid type expression", 115 Detail: fmt.Sprintf("A type is required, not %s.", result.Type().FriendlyName()), 116 }) 117 return cty.DynamicPseudoType, diags 118 } 119 120 return unwrapTypeType(result), diags 121 } 122 123 func wrapTypeType(ty cty.Type) cty.Value { 124 return cty.CapsuleVal(typeType, &ty) 125 } 126 127 func unwrapTypeType(val cty.Value) cty.Type { 128 return *(val.EncapsulatedValue().(*cty.Type)) 129 }