github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/cmd/signature-fuzzer/internal/fuzz-generator/arrayparm.go (about)

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package generator
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  )
    11  
    12  // arrayparm describes a parameter of array type; it implements the
    13  // "parm" interface.
    14  type arrayparm struct {
    15  	aname     string
    16  	qname     string
    17  	nelements uint8
    18  	eltype    parm
    19  	slice     bool
    20  	isBlank
    21  	addrTakenHow
    22  	isGenValFunc
    23  	skipCompare
    24  }
    25  
    26  func (p arrayparm) IsControl() bool {
    27  	return false
    28  }
    29  
    30  func (p arrayparm) TypeName() string {
    31  	return p.aname
    32  }
    33  
    34  func (p arrayparm) QualName() string {
    35  	return p.qname
    36  }
    37  
    38  func (p arrayparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {
    39  	n := p.aname
    40  	if caller {
    41  		n = p.qname
    42  	}
    43  	b.WriteString(fmt.Sprintf("%s %s%s", prefix, n, suffix))
    44  }
    45  
    46  func (p arrayparm) String() string {
    47  	return fmt.Sprintf("%s %d-element array of %s", p.aname, p.nelements, p.eltype.String())
    48  }
    49  
    50  func (p arrayparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {
    51  	var buf bytes.Buffer
    52  
    53  	verb(5, "arrayparm.GenValue(%d)", value)
    54  
    55  	n := p.aname
    56  	if caller {
    57  		n = p.qname
    58  	}
    59  	buf.WriteString(fmt.Sprintf("%s{", n))
    60  	for i := 0; i < int(p.nelements); i++ {
    61  		var valstr string
    62  		valstr, value = s.GenValue(f, p.eltype, value, caller)
    63  		writeCom(&buf, i)
    64  		buf.WriteString(valstr)
    65  	}
    66  	buf.WriteString("}")
    67  	return buf.String(), value
    68  }
    69  
    70  func (p arrayparm) GenElemRef(elidx int, path string) (string, parm) {
    71  	ene := p.eltype.NumElements()
    72  	verb(4, "begin GenElemRef(%d,%s) on %s ene %d", elidx, path, p.String(), ene)
    73  
    74  	// For empty arrays, convention is to return empty string
    75  	if ene == 0 {
    76  		return "", &p
    77  	}
    78  
    79  	// Find slot within array of element of interest
    80  	slot := elidx / ene
    81  
    82  	// If this is the element we're interested in, return it
    83  	if ene == 1 {
    84  		verb(4, "hit scalar element")
    85  		epath := fmt.Sprintf("%s[%d]", path, slot)
    86  		if path == "_" || p.IsBlank() {
    87  			epath = "_"
    88  		}
    89  		return epath, p.eltype
    90  	}
    91  
    92  	verb(4, "recur slot=%d GenElemRef(%d,...)", slot, elidx-(slot*ene))
    93  
    94  	// Otherwise our victim is somewhere inside the slot
    95  	ppath := fmt.Sprintf("%s[%d]", path, slot)
    96  	if p.IsBlank() {
    97  		ppath = "_"
    98  	}
    99  	return p.eltype.GenElemRef(elidx-(slot*ene), ppath)
   100  }
   101  
   102  func (p arrayparm) NumElements() int {
   103  	return p.eltype.NumElements() * int(p.nelements)
   104  }
   105  
   106  func (p arrayparm) HasPointer() bool {
   107  	return p.eltype.HasPointer() || p.slice
   108  }