func (s *Struct) IfZeroExpr() string {
	if s.alias == "" {
		return ""  
	}
	var res string
	for i := range s.Fields {
		if !ast.IsExported(s.Fields[i].FieldName) {
			continue
		}
		fieldZero := s.Fields[i].FieldElem.IfZeroExpr()
		if fieldZero != "" {
			if res != "" {
				res += " && "
			}
			res += "(" + fieldZero + ")"
		}
	}
	return res
}
IfZeroExpr returns the expression to compare to zero/empty.
package gen
import (
	"fmt"
	"go/ast"
	"strconv"
	"strings"
)
var (
	identNext   = 0
	identPrefix = "za"
)
func resetIdent(prefix string) {
	identPrefix = prefix
	identNext = 0
}
func randIdent() string {
	identNext++
	return fmt.Sprintf("%s%04d", identPrefix, identNext)
}
type Primitive uint8
const (
	Invalid Primitive = iota
	Bytes
	String
	Float32
	Float64
	Complex64
	Complex128
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Byte
	Int
	Int8
	Int16
	Int32
	Int64
	Bool
	Intf   
	Time   
	Ext    
	Error  
	IDENT  
)
var primitives = map[string]Primitive{
	"[]byte":         Bytes,
	"string":         String,
	"float32":        Float32,
	"float64":        Float64,
	"complex64":      Complex64,
	"complex128":     Complex128,
	"uint":           Uint,
	"uint8":          Uint8,
	"uint16":         Uint16,
	"uint32":         Uint32,
	"uint64":         Uint64,
	"uintptr":        Uintptr,
	"byte":           Byte,
	"rune":           Int32,
	"int":            Int,
	"int8":           Int8,
	"int16":          Int16,
	"int32":          Int32,
	"int64":          Int64,
	"bool":           Bool,
	"interface{}":    Intf,
	"time.Time":      Time,
	"msgp.Extension": Ext,
	"error":          Error,
}
var builtins = map[string]struct{}{
	"msgp.Raw":    struct{}{},
	"msgp.Number": struct{}{},
}
type Callback struct {
	Fname        string
	CallbackType CallbackType
}
type CallbackType uint64
const UnmarshalCallBack CallbackType = 1
func (c Callback) IsUnmarshallCallback() bool { return c.CallbackType == UnmarshalCallBack }
func (c Callback) GetName() string            { return c.Fname }
type common struct {
	vname, alias string
	allocbound   string
	callbacks    []Callback
}
func (c *common) SetVarname(s string)      { c.vname = s }
func (c *common) Varname() string          { return c.vname }
func (c *common) Alias(typ string)         { c.alias = typ }
func (c *common) SortInterface() string    { return "" }
func (c *common) SetAllocBound(s string)   { c.allocbound = s }
func (c *common) AllocBound() string       { return c.allocbound }
func (c *common) GetCallbacks() []Callback { return c.callbacks }
func (c *common) AddCallback(cb Callback)  { c.callbacks = append(c.callbacks, cb) }
func (c *common) hidden()                  {}
func IsDangling(e Elem) bool {
	if be, ok := e.(*BaseElem); ok && be.Dangling() {
		return true
	}
	return false
}
type Elem interface {
	SetVarname(s string)
	Varname() string
	TypeName() string
	Alias(typ string)
	Copy() Elem
	Complexity() int
	ZeroExpr() string
	IfZeroExpr() string
	SortInterface() string
	Comparable() bool
	SetAllocBound(bound string)
	AllocBound() string
	AddCallback(Callback)
	GetCallbacks() []Callback
	hidden()
}
func Ident(importPrefix string, id string) *BaseElem {
	p, ok := primitives[id]
	if ok {
		return &BaseElem{Value: p}
	}
	id = importPrefix + id
	be := &BaseElem{Value: IDENT, IdentName: id}
	be.Alias(id)
	return be
}
type Array struct {
	common
	Index    string  
	Size     string  
	SizeHint string  
	Els      Elem    
}
func (a *Array) SetVarname(s string) {
	a.common.SetVarname(s)
ridx:
	a.Index = randIdent()
	if strings.Contains(a.Varname(), a.Index) {
		goto ridx
	}
	a.Els.SetVarname(fmt.Sprintf("%s[%s]", a.Varname(), a.Index))
}
func (a *Array) TypeName() string {
	if a.common.alias != "" {
		return a.common.alias
	}
	a.common.Alias(fmt.Sprintf("[%s]%s", a.Size, a.Els.TypeName()))
	return a.common.alias
}
func (a *Array) Copy() Elem {
	b := *a
	b.Els = a.Els.Copy()
	return &b
}
func (a *Array) Complexity() int { return 1 + a.Els.Complexity() }
func (a *Array) sz() int {
	szString := a.SizeHint
	if szString == "" {
		szString = a.Size
	}
	s, err := strconv.Atoi(szString)
	if err != nil {
		panic(err)
	}
	return s
}
func (a *Array) ZeroExpr() string {
	zeroElem := a.Els.ZeroExpr()
	if zeroElem == "" {
		return ""
	}
	sz := a.sz()
	res := fmt.Sprintf("%s{", a.TypeName())
	for i := 0; i < sz; i++ {
		res += fmt.Sprintf("%s, ", zeroElem)
	}
	res += "}"
	return res
}
func (a *Array) IfZeroExpr() string {
	if a.Els.Comparable() {
		return fmt.Sprintf("%s == (%s{})", a.Varname(), a.TypeName())
	}
	sz := a.sz()
	var res string
	for i := 0; i < sz; i++ {
		el := a.Els.Copy()
		el.SetVarname(fmt.Sprintf("%s[%d]", a.Varname(), i))
		if res != "" {
			res += " && "
		}
		res += "(" + el.IfZeroExpr() + ")"
	}
	return res
}
func (a *Array) Comparable() bool {
	return a.Els.Comparable()
}
type Map struct {
	common
	Keyidx string  
	Key    Elem    
	Validx string  
	Value  Elem    
}
func (m *Map) SetVarname(s string) {
	m.common.SetVarname(s)
ridx:
	m.Keyidx = randIdent()
	m.Validx = randIdent()
	if m.Keyidx == m.Validx {
		goto ridx
	}
	m.Key.SetVarname(m.Keyidx)
	m.Value.SetVarname(m.Validx)
}
func (m *Map) TypeName() string {
	if m.common.alias != "" {
		return m.common.alias
	}
	m.common.Alias("map[" + m.Key.TypeName() + "]" + m.Value.TypeName())
	return m.common.alias
}
func (m *Map) Copy() Elem {
	g := *m
	g.Key = m.Key.Copy()
	g.Value = m.Value.Copy()
	return &g
}
func (m *Map) Complexity() int { return 2 + m.Value.Complexity() }
func (m *Map) ZeroExpr() string { return "nil" }
func (m *Map) IfZeroExpr() string { return "len(" + m.Varname() + ") == 0" }
func (m *Map) Comparable() bool {
	return false
}
type Slice struct {
	common
	Index string
	Els   Elem  
}
func (s *Slice) SetVarname(a string) {
	s.common.SetVarname(a)
	s.Index = randIdent()
	varName := s.Varname()
	if varName[0] == '*' {
		varName = "(" + varName + ")"
	}
	s.Els.SetVarname(fmt.Sprintf("%s[%s]", varName, s.Index))
}
func (s *Slice) TypeName() string {
	if s.common.alias != "" {
		return s.common.alias
	}
	s.common.Alias("[]" + s.Els.TypeName())
	return s.common.alias
}
func (s *Slice) Copy() Elem {
	z := *s
	z.Els = s.Els.Copy()
	return &z
}
func (s *Slice) Complexity() int {
	return 1 + s.Els.Complexity()
}
func (s *Slice) ZeroExpr() string { return "nil" }
func (s *Slice) IfZeroExpr() string { return "len(" + s.Varname() + ") == 0" }
func (s *Slice) Comparable() bool {
	return false
}
type Ptr struct {
	common
	Value Elem
}
func (s *Ptr) SetVarname(a string) {
	s.common.SetVarname(a)
	switch x := s.Value.(type) {
	case *Struct:
		x.SetVarname(a)
		return
	case *BaseElem:
		if x.Value == IDENT {
			x.SetVarname(a)
		} else {
			x.SetVarname("*" + a)
		}
		return
	default:
		s.Value.SetVarname("*" + a)
		return
	}
}
func (s *Ptr) TypeName() string {
	if s.common.alias != "" {
		return s.common.alias
	}
	s.common.Alias("*" + s.Value.TypeName())
	return s.common.alias
}
func (s *Ptr) Copy() Elem {
	v := *s
	v.Value = s.Value.Copy()
	return &v
}
func (s *Ptr) Complexity() int { return 1 + s.Value.Complexity() }
func (s *Ptr) Needsinit() bool {
	if be, ok := s.Value.(*BaseElem); ok && be.needsref {
		return false
	}
	return true
}
func (s *Ptr) ZeroExpr() string { return "nil" }
func (s *Ptr) IfZeroExpr() string { return s.Varname() + " == nil" }
func (s *Ptr) Comparable() bool {
	return false
}
type Struct struct {
	common
	Fields  []StructField  
	AsTuple bool           
}
func (s *Struct) TypeName() string {
	if s.common.alias != "" {
		return s.common.alias
	}
	str := "struct{\n"
	for i := range s.Fields {
		str += s.Fields[i].FieldName +
			" " + s.Fields[i].FieldElem.TypeName() +
			" " + s.Fields[i].RawTag + ";\n"
	}
	str += "}"
	s.common.Alias(str)
	return s.common.alias
}
func (s *Struct) SetVarname(a string) {
	s.common.SetVarname(a)
	writeStructFields(s.Fields, a)
}
func (s *Struct) Copy() Elem {
	g := *s
	g.Fields = make([]StructField, len(s.Fields))
	copy(g.Fields, s.Fields)
	for i := range s.Fields {
		g.Fields[i].FieldElem = s.Fields[i].FieldElem.Copy()
	}
	return &g
}
func (s *Struct) Complexity() int {
	c := 1
	for i := range s.Fields {
		c += s.Fields[i].FieldElem.Complexity()
	}
	return c
}
func (s *Struct) ZeroExpr() string {
	if s.alias == "" {
		return ""  
	}
	return "(" + s.TypeName() + "{})"
}