github.com/hashicorp/packer@v1.14.3/hcl2template/function/length.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package function 5 6 import ( 7 "errors" 8 9 "github.com/zclconf/go-cty/cty" 10 "github.com/zclconf/go-cty/cty/function" 11 "github.com/zclconf/go-cty/cty/function/stdlib" 12 ) 13 14 var LengthFunc = function.New(&function.Spec{ 15 Params: []function.Parameter{ 16 { 17 Name: "value", 18 Type: cty.DynamicPseudoType, 19 AllowDynamicType: true, 20 AllowUnknown: true, 21 }, 22 }, 23 Type: func(args []cty.Value) (cty.Type, error) { 24 collTy := args[0].Type() 25 switch { 26 case collTy == cty.String || collTy.IsTupleType() || collTy.IsObjectType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType: 27 return cty.Number, nil 28 default: 29 return cty.Number, errors.New("argument must be a string, a collection type, or a structural type") 30 } 31 }, 32 RefineResult: refineNotNull, 33 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 34 coll := args[0] 35 collTy := args[0].Type() 36 switch { 37 case collTy == cty.DynamicPseudoType: 38 return cty.UnknownVal(cty.Number), nil 39 case collTy.IsTupleType(): 40 l := len(collTy.TupleElementTypes()) 41 return cty.NumberIntVal(int64(l)), nil 42 case collTy.IsObjectType(): 43 l := len(collTy.AttributeTypes()) 44 return cty.NumberIntVal(int64(l)), nil 45 case collTy == cty.String: 46 // We'll delegate to the cty stdlib strlen function here, because 47 // it deals with all of the complexities of tokenizing unicode 48 // grapheme clusters. 49 return stdlib.Strlen(coll) 50 case collTy.IsListType() || collTy.IsSetType() || collTy.IsMapType(): 51 return coll.Length(), nil 52 default: 53 // Should never happen, because of the checks in our Type func above 54 return cty.UnknownVal(cty.Number), errors.New("impossible value type for length(...)") 55 } 56 }, 57 }) 58 59 // Length returns the number of elements in the given collection or number of 60 // Unicode characters in the given string. 61 func Length(collection cty.Value) (cty.Value, error) { 62 return LengthFunc.Call([]cty.Value{collection}) 63 }