func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
	if allowSlice {
		maybeItem := guessType(scanner, raw, false)
		subRaw := raw[scanner.Pos().Offset:]
		subScanner := parserScanner(subRaw, scanner.Error)
		var tok rune
		for tok = subScanner.Scan(); tok != ',' && tok != sc.EOF && tok != ';'; tok = subScanner.Scan() {
		}
		if tok == ';' {
			return &Argument{
				Type:     SliceType,
				ItemType: maybeItem,
			}
		}
		return maybeItem
	}
	subRaw := raw[scanner.Pos().Offset:]
	subScanner := parserScanner(subRaw, scanner.Error)
	hint := peekNoSpace(subScanner)
	switch hint {
	case '"', '\'', '`':
		return &Argument{Type: StringType}
	}
	if hint == '{' {
		subScanner.Scan()
		firstElemType := guessType(subScanner, subRaw, false)
		if firstElemType.Type == StringType {
			var keyVal string  
			(&Argument{Type: StringType}).parseString(subScanner, raw, reflect.Indirect(reflect.ValueOf(&keyVal)))
			if subScanner.Scan() == ':' {
				return &Argument{
					Type:     MapType,
					ItemType: &Argument{Type: AnyType},
				}
			}
		}
		return &Argument{
			Type:     SliceType,
			ItemType: firstElemType,
		}
	}
	probablyString := false
	if hint == 't' || hint == 'f' {
		if nextTok := subScanner.Scan(); nextTok == sc.Ident {
			switch subScanner.TokenText() {
			case "true", "false":
				return &Argument{Type: BoolType}
			}
			probablyString = true
		} else {
			scanner.Error(scanner, fmt.Sprintf("got a token (%q) that looked like an ident, but was not", scanner.TokenText()))
			return &Argument{Type: InvalidType}
		}
	}
	if !probablyString {
		nextTok := subScanner.Scan()
		if nextTok == '-' {
			nextTok = subScanner.Scan()
		}
		if nextTok == sc.Int {
			return &Argument{Type: IntType}
		}
	}
	return &Argument{Type: StringType}
}
guessType takes an educated guess about the type of the next field.  If allowSlice
is false, it will not guess slices.  It's less efficient than parsing with actual
type information, since we need to allocate to peek ahead full tokens, and the scanner
only allows peeking ahead one character.
Maps are *always* non-uniform (i.e. type the AnyType item type), since they're frequently
used to represent things like defaults for an object in JSON.
package markers
import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	sc "text/scanner"
	"unicode"
	"sigs.k8s.io/controller-tools/pkg/loader"
)
func expect(scanner *sc.Scanner, expected rune, errDesc string) bool {
	tok := scanner.Scan()
	if tok != expected {
		scanner.Error(scanner, fmt.Sprintf("expected %s, got %q", errDesc, scanner.TokenText()))
		return false
	}
	return true
}
func peekNoSpace(scanner *sc.Scanner) rune {
	hint := scanner.Peek()
	for ; hint <= rune(' ') && ((1<<uint64(hint))&scanner.Whitespace) != 0; hint = scanner.Peek() {
		scanner.Next()  
	}
	return hint
}
var (
	interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
	rawArgsType   = reflect.TypeOf((*RawArguments)(nil)).Elem()
)
func lowerCamelCase(in string) string {
	isFirst := true
	return strings.Map(func(inRune rune) rune {
		if isFirst {
			isFirst = false
			return unicode.ToLower(inRune)
		}
		return inRune
	}, in)
}
type RawArguments []byte
type ArgumentType int
const (
	InvalidType ArgumentType = iota
	IntType
	StringType
	BoolType
	AnyType
	SliceType
	MapType
	RawType
)
type Argument struct {
	Type ArgumentType
	Optional bool
	Pointer bool
	ItemType *Argument
}
func (a Argument) typeString(out *strings.Builder) {
	if a.Pointer {
		out.WriteRune('*')
	}
	switch a.Type {
	case InvalidType:
		out.WriteString("<invalid>")
	case IntType:
		out.WriteString("int")
	case StringType:
		out.WriteString("string")
	case BoolType:
		out.WriteString("bool")
	case AnyType:
		out.WriteString("<any>")
	case SliceType:
		out.WriteString("[]")
		a.ItemType.typeString(out)
	case MapType:
		out.WriteString("map[string]")
		a.ItemType.typeString(out)
	case RawType:
		out.WriteString("<raw>")
	}
}
func (a Argument) TypeString() string {
	out := &strings.Builder{}
	a.typeString(out)
	return out.String()
}
func (a Argument) String() string {
	if a.Optional {
		return fmt.Sprintf("<optional arg %s>", a.TypeString())
	}
	return fmt.Sprintf("<arg %s>", a.TypeString())
}
func castAndSet(out, val reflect.Value) {
	outType := out.Type()
	if outType != val.Type() {
		val = val.Convert(outType)
	}
	out.Set(val)
}
func makeSliceType(itemType Argument) (reflect.Type, error) {
	var itemReflectedType reflect.Type
	switch itemType.Type {
	case IntType:
		itemReflectedType = reflect.TypeOf(int(0))
	case StringType:
		itemReflectedType = reflect.TypeOf("")
	case BoolType:
		itemReflectedType = reflect.TypeOf(false)
	case SliceType:
		subItemType, err := makeSliceType(*itemType.ItemType)
		if err != nil {
			return nil, err
		}
		itemReflectedType = subItemType
	case MapType:
		subItemType, err := makeMapType(*itemType.ItemType)
		if err != nil {
			return nil, err
		}
		itemReflectedType = subItemType
	default:
		return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
	}
	if itemType.Pointer {
		itemReflectedType = reflect.PtrTo(itemReflectedType)
	}
	return reflect.SliceOf(itemReflectedType), nil
}
func makeMapType(itemType Argument) (reflect.Type, error) {
	var itemReflectedType reflect.Type
	switch itemType.Type {
	case IntType:
		itemReflectedType = reflect.TypeOf(int(0))
	case StringType:
		itemReflectedType = reflect.TypeOf("")
	case BoolType:
		itemReflectedType = reflect.TypeOf(false)
	case SliceType:
		subItemType, err := makeSliceType(*itemType.ItemType)
		if err != nil {
			return nil, err
		}
		itemReflectedType = subItemType
	case MapType:
		subItemType, err := makeMapType(*itemType.ItemType)
		if err != nil {
			return nil, err
		}
		itemReflectedType = subItemType
	case AnyType:
		itemReflectedType = interfaceType
	default:
		return nil, fmt.Errorf("invalid type when constructing guessed slice out: %v", itemType.Type)
	}
	if itemType.Pointer {
		itemReflectedType = reflect.PtrTo(itemReflectedType)
	}
	return reflect.MapOf(reflect.TypeOf(""), itemReflectedType), nil
}