func ExtractShortPackage(pkgPath []byte) string {
	parts := bytes.Split(pkgPath, []byte{'/'})
	shortPkg := parts[len(parts)-1]
	if bytes.HasPrefix(shortPkg, []byte{'v'}) && majorVersionRegexp.Match(shortPkg) {
		shortPkg = parts[len(parts)-2]
	}
	return string(shortPkg)
}
ExtractShortPackage gets the last part of a package path like "generate" in
"github.com/jschaf/pggen/generate".
package gotype
import (
	"bytes"
	"github.com/jschaf/pggen/internal/casing"
	"github.com/jschaf/pggen/internal/pg"
	"regexp"
	"strconv"
	"strings"
	"unicode"
)
type Type interface {
	QualifyRel(pkgPath string) string
	Import() string
	Package() string
	BaseName() string
	PgType() pg.Type
}
type (
	VoidType struct{}
	ArrayType struct {
		PgArray pg.ArrayType  
		PkgPath string        
		Pkg     string        
		Name    string        
		Elem    Type          
	}
	EnumType struct {
		PgEnum  pg.EnumType  
		PkgPath string
		Pkg     string
		Name    string
		Labels []string
		Values []string
	}
	OpaqueType struct {
		PgTyp   pg.Type  
		PkgPath string
		Pkg     string
		Name    string
	}
	CompositeType struct {
		PgComposite pg.CompositeType  
		PkgPath     string
		Pkg         string
		Name        string    
		FieldNames  []string  
		FieldTypes  []Type
	}
)
func (e VoidType) QualifyRel(pkgPath string) string { return qualifyRel(e, pkgPath) }
func (e VoidType) Import() string                   { return "" }
func (e VoidType) Package() string                  { return "" }
func (e VoidType) BaseName() string                 { return "" }
func (e VoidType) PgType() pg.Type                  { return pg.VoidType{} }
func (a ArrayType) QualifyRel(pkgPath string) string { return qualifyRel(a, pkgPath) }
func (a ArrayType) Import() string                   { return a.PkgPath }
func (a ArrayType) Package() string                  { return a.Pkg }
func (a ArrayType) BaseName() string                 { return a.Name }
func (a ArrayType) PgType() pg.Type                  { return a.PgArray }
func (e EnumType) QualifyRel(pkgPath string) string { return qualifyRel(e, pkgPath) }
func (e EnumType) Import() string                   { return e.PkgPath }
func (e EnumType) Package() string                  { return e.Pkg }
func (e EnumType) BaseName() string                 { return e.Name }
func (e EnumType) PgType() pg.Type                  { return e.PgEnum }
func (o OpaqueType) QualifyRel(pkgPath string) string { return qualifyRel(o, pkgPath) }
func (o OpaqueType) Import() string                   { return o.PkgPath }
func (o OpaqueType) Package() string                  { return o.Pkg }
func (o OpaqueType) BaseName() string                 { return o.Name }
func (o OpaqueType) PgType() pg.Type                  { return o.PgTyp }
func (c CompositeType) QualifyRel(pkgPath string) string { return qualifyRel(c, pkgPath) }
func (c CompositeType) Import() string                   { return c.PkgPath }
func (c CompositeType) Package() string                  { return c.Pkg }
func (c CompositeType) BaseName() string                 { return c.Name }
func (c CompositeType) PgType() pg.Type                  { return c.PgComposite }
func qualifyRel(typ Type, otherPkgPath string) string {
	if typ.Import() == otherPkgPath || typ.Import() == "" || typ.Package() == "" {
		return typ.BaseName()
	}
	if !strings.ContainsRune(otherPkgPath, '.') && typ.Package() == otherPkgPath {
		return typ.BaseName()
	}
	sb := strings.Builder{}
	sb.Grow(len(typ.BaseName()))
	if typ.Import() != "" {
		shortPkg := typ.Package()
		sb.Grow(len(shortPkg) + 1)
		sb.WriteString(shortPkg)
		sb.WriteRune('.')
	}
	sb.WriteString(typ.BaseName())
	return sb.String()
}
func NewArrayType(pkgPath string, pgArray pg.ArrayType, caser casing.Caser, elemType Type) ArrayType {
	name := caser.ToUpperGoIdent(pgArray.Name)
	if name == "" {
		name = ChooseFallbackName(pgArray.Name, "UnnamedArray")
	}
	return ArrayType{
		PgArray: pgArray,
		PkgPath: pkgPath,
		Pkg:     ExtractShortPackage([]byte(pkgPath)),
		Name:    "[]" + name,
		Elem:    elemType,
	}
}
func NewEnumType(pkgPath string, pgEnum pg.EnumType, caser casing.Caser) EnumType {
	name := caser.ToUpperGoIdent(pgEnum.Name)
	if name == "" {
		name = ChooseFallbackName(pgEnum.Name, "UnnamedEnum")
	}
	labels := make([]string, len(pgEnum.Labels))
	values := make([]string, len(pgEnum.Labels))
	for i, label := range pgEnum.Labels {
		ident := caser.ToUpperGoIdent(label)
		if ident == "" {
			ident = ChooseFallbackName(label, "UnnamedLabel"+strconv.Itoa(i))
		}
		labels[i] = name + ident
		values[i] = pgEnum.Labels[i]
	}
	return EnumType{
		PgEnum:  pgEnum,
		PkgPath: pkgPath,
		Pkg:     ExtractShortPackage([]byte(pkgPath)),
		Name:    name,
		Labels:  labels,
		Values:  values,
	}
}
func NewOpaqueType(qualType string) OpaqueType {
	if !strings.ContainsRune(qualType, '.') {
		return OpaqueType{Name: qualType}  
	}
	bs := []byte(qualType)
	isArr := bs[0] == '[' && bs[1] == ']'
	if isArr {
		bs = bs[2:]
	}
	isPtr := bs[0] == '*'
	if isPtr {
		bs = bs[1:]
	}
	idx := bytes.LastIndexByte(bs, '.')
	name := string(bs[idx+1:])
	if isPtr {
		name = "*" + name
	}
	if isArr {
		name = "[]" + name
	}
	pkgPath := bs[:idx]
	shortPkg := ExtractShortPackage(pkgPath)
	return OpaqueType{
		PkgPath: string(pkgPath),
		Pkg:     shortPkg,
		Name:    name,
	}
}
var majorVersionRegexp = regexp.MustCompile(`^v[0-9]+$`)