go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/llx/types.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package llx 5 6 import ( 7 "go.mondoo.com/cnquery/types" 8 ) 9 10 // Type of this chunk, by looking at either the primitive or function. 11 // The type is not be dereferenced! (i.e. ref's remain) 12 func (c *Chunk) Type() types.Type { 13 // call: primitive 14 if c.Call == Chunk_PRIMITIVE { 15 return types.Type(c.Primitive.Type) 16 } 17 18 // call: function 19 if c.Function != nil { 20 return types.Type(c.Function.Type) 21 } 22 23 // call: property 24 if c.Primitive != nil { 25 return types.Type(c.Primitive.Type) 26 } 27 28 // Chunks that don't have a function call but do have an ID are resources. 29 // They are bound globally (because otherwise they'd have a function) and 30 // they are not primitive (we eliminate those above). They could still be 31 // global non-functions, but we need to investigate that case. 32 if c.Id != "" { 33 return types.Resource(c.Id) 34 } 35 36 return types.Any 37 } 38 39 func (p *Primitive) typeStringV1(typ types.Type, stack *CodeV1) string { 40 switch typ.Underlying() { 41 case types.Ref: 42 idx := bytes2int(p.Value) 43 ref := stack.Code[idx-1] 44 return ref.Primitive.typeStringV1(ref.Type(), stack) 45 case types.ArrayLike: 46 return "[]" + p.typeStringV1(typ.Child(), stack) 47 case types.MapLike: 48 return "map[" + p.typeStringV1(typ.Key(), stack) + "]" + p.typeStringV1(typ.Child(), stack) 49 default: 50 return typ.Label() 51 } 52 } 53 54 // TypeString for the dereferenced type label of this primitive 55 func (p *Primitive) TypeStringV1(stack *CodeV1) string { 56 return p.typeStringV1(types.Type(p.Type), stack) 57 } 58 59 // turns any "ref" types into whatever they are referencing 60 func (p *Primitive) dereferenceTypeV1(typ types.Type, stack *CodeV1) types.Type { 61 switch typ.Underlying() { 62 case types.Ref: 63 idx := bytes2int(p.Value) 64 ref := stack.Code[idx-1] 65 return ref.Primitive.dereferenceTypeV1(ref.Type(), stack) 66 case types.ArrayLike: 67 k := p.dereferenceTypeV1(typ.Child(), stack) 68 return types.Array(k) 69 case types.MapLike: 70 k := p.dereferenceTypeV1(typ.Key(), stack) 71 v := p.dereferenceTypeV1(typ.Child(), stack) 72 return types.Map(k, v) 73 default: 74 return typ 75 } 76 } 77 78 // DereferencedType of this chunk, resolved if it is a reference to anything. 79 func (c *Chunk) DereferencedTypeV1(stack *CodeV1) types.Type { 80 if c.Call == Chunk_PRIMITIVE { 81 return c.Primitive.dereferenceTypeV1(types.Type(c.Primitive.Type), stack) 82 } 83 84 if c.Function != nil { 85 return types.Type(c.Function.Type) 86 } 87 88 if c.Primitive != nil { 89 return c.Primitive.dereferenceTypeV1(types.Type(c.Primitive.Type), stack) 90 } 91 92 return types.Any 93 } 94 95 // ArrayType for the given list of primitives 96 func ArrayTypeV1(arr []*Primitive, stack *CodeV1) types.Type { 97 if arr == nil || len(arr) == 0 { 98 return types.Array(types.Unset) 99 } 100 101 sharedType := arr[0].dereferenceTypeV1(types.Type(arr[0].Type), stack) 102 for i := 1; i < len(arr); i++ { 103 // we are done if not all elements have the same type 104 ct := arr[i].dereferenceTypeV1(types.Type(arr[i].Type), stack) 105 if ct != sharedType { 106 return types.Array(types.Any) 107 } 108 } 109 110 return types.Array(sharedType) 111 } 112 113 // turns any "ref" types into whatever they are referencing 114 func (p *Primitive) dereferenceTypeV2(typ types.Type, stack *CodeV2) types.Type { 115 switch typ.Underlying() { 116 case types.Ref: 117 ref := uint64(bytes2int(p.Value)) 118 chunk := stack.Chunk(ref) 119 return chunk.Primitive.dereferenceTypeV2(chunk.Type(), stack) 120 case types.ArrayLike: 121 k := p.dereferenceTypeV2(typ.Child(), stack) 122 return types.Array(k) 123 case types.MapLike: 124 k := p.dereferenceTypeV2(typ.Key(), stack) 125 v := p.dereferenceTypeV2(typ.Child(), stack) 126 return types.Map(k, v) 127 default: 128 return typ 129 } 130 } 131 132 // DereferencedType of this chunk, resolved if it is a reference to anything. 133 func (c *Chunk) DereferencedTypeV2(stack *CodeV2) types.Type { 134 if c.Call == Chunk_PRIMITIVE { 135 return c.Primitive.dereferenceTypeV2(types.Type(c.Primitive.Type), stack) 136 } 137 138 if c.Function != nil { 139 return types.Type(c.Function.Type) 140 } 141 142 if c.Primitive != nil { 143 return c.Primitive.dereferenceTypeV2(types.Type(c.Primitive.Type), stack) 144 } 145 146 return types.Any 147 } 148 149 // ArrayType for the given list of primitives 150 func ArrayTypeV2(arr []*Primitive, stack *CodeV2) types.Type { 151 if arr == nil || len(arr) == 0 { 152 return types.Array(types.Unset) 153 } 154 155 sharedType := arr[0].dereferenceTypeV2(types.Type(arr[0].Type), stack) 156 for i := 1; i < len(arr); i++ { 157 // we are done if not all elements have the same type 158 ct := arr[i].dereferenceTypeV2(types.Type(arr[i].Type), stack) 159 if ct != sharedType { 160 return types.Array(types.Any) 161 } 162 } 163 164 return types.Array(sharedType) 165 }