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  }