github.com/xhebox/bstruct@v0.0.0-20221115052913-86d4d6d98866/field.go (about)

     1  package bstruct
     2  
     3  import (
     4  	"go/ast"
     5  )
     6  
     7  type Coder func(rdwt ast.Expr, ptr ast.Expr, s *Field) []ast.Stmt
     8  
     9  type FieldType uint
    10  
    11  const (
    12  	FieldInvalid FieldType = iota
    13  	FieldBool
    14  	FieldInt8
    15  	FieldInt16
    16  	FieldInt32
    17  	FieldInt64
    18  	FieldUint8
    19  	FieldUint16
    20  	FieldUint32
    21  	FieldUint64
    22  	FieldFloat32
    23  	FieldFloat64
    24  	FieldString
    25  	FieldSlice
    26  	FieldStruct
    27  	FieldCustom
    28  )
    29  
    30  func (ft FieldType) IsPrimitive() bool {
    31  	switch ft {
    32  	case FieldBool, FieldFloat32, FieldFloat64, FieldInt8, FieldInt16, FieldInt32, FieldInt64, FieldUint8, FieldUint16, FieldUint32, FieldUint64:
    33  		return true
    34  	default:
    35  		return false
    36  	}
    37  }
    38  
    39  func (ft FieldType) String() string {
    40  	switch ft {
    41  	case FieldBool:
    42  		return "bool"
    43  	case FieldInt8:
    44  		return "int8"
    45  	case FieldInt16:
    46  		return "int16"
    47  	case FieldInt32:
    48  		return "int32"
    49  	case FieldInt64:
    50  		return "int64"
    51  	case FieldUint8:
    52  		return "uint8"
    53  	case FieldUint16:
    54  		return "uint16"
    55  	case FieldUint32:
    56  		return "uint32"
    57  	case FieldUint64:
    58  		return "uint64"
    59  	case FieldFloat32:
    60  		return "float32"
    61  	case FieldFloat64:
    62  		return "float64"
    63  	case FieldString:
    64  		return "string"
    65  	case FieldSlice:
    66  		return "slice"
    67  	case FieldStruct:
    68  		return "struct"
    69  	default:
    70  		return "invalid"
    71  	}
    72  }
    73  
    74  func (ft FieldType) Size() uint {
    75  	sz := uint(0)
    76  	switch ft {
    77  	case FieldBool, FieldInt8, FieldUint8:
    78  		sz = 1
    79  	case FieldInt16, FieldUint16:
    80  		sz = 2
    81  	case FieldInt32, FieldUint32, FieldFloat32:
    82  		sz = 4
    83  	case FieldInt64, FieldUint64, FieldFloat64:
    84  		sz = 8
    85  	}
    86  	return sz
    87  }
    88  
    89  func (ft FieldType) IsType(t FieldType) bool {
    90  	return ft == t
    91  }
    92  
    93  type StructField struct {
    94  	*Field
    95  	strucName string
    96  	comment   string
    97  	optional  bool
    98  }
    99  
   100  type Field struct {
   101  	// all
   102  	typename string
   103  	comment  string
   104  	typ      FieldType
   105  	virtual  bool
   106  	// FieldSlice
   107  	sliceType *Field
   108  	// FieldStruct
   109  	strucFields []StructField
   110  	// FieldCustom
   111  	custyp ast.Expr
   112  	cusenc Coder
   113  	cusdec Coder
   114  }
   115  
   116  func New(typ FieldType) *Field {
   117  	if typ.IsType(FieldSlice) || typ.IsType(FieldString) {
   118  		panic("should not pass slice or string type")
   119  	}
   120  	return &Field{
   121  		typ: typ,
   122  	}
   123  }
   124  
   125  func NewSlice(t *Field) *Field {
   126  	return &Field{
   127  		typ:       FieldSlice,
   128  		sliceType: t,
   129  	}
   130  }
   131  
   132  func NewString() *Field {
   133  	return &Field{
   134  		typ:       FieldString,
   135  		sliceType: New(FieldUint8),
   136  	}
   137  }
   138  
   139  func NewCustom(typ ast.Expr, enc, dec Coder) *Field {
   140  	if typ == nil {
   141  		panic("typ can not be nil")
   142  	}
   143  	return &Field{
   144  		typ:    FieldCustom,
   145  		custyp: typ,
   146  		cusenc: enc,
   147  		cusdec: dec,
   148  	}
   149  }
   150  
   151  func (b *Field) Add(name, comment string, optional bool, field *Field) *Field {
   152  	b.strucFields = append(b.strucFields, StructField{
   153  		comment:   comment,
   154  		optional:  optional,
   155  		strucName: name,
   156  		Field:     field,
   157  	})
   158  	return b
   159  }
   160  
   161  func (b *Field) Comment(comment string) *Field {
   162  	b.comment = comment
   163  	return b
   164  }
   165  
   166  func (s *Field) Virtual() *Field {
   167  	s.virtual = true
   168  	return s
   169  }
   170  
   171  func (s *Field) Reg(e *Builder, name string) *Field {
   172  	s.typename = name
   173  	e.types[name] = builtField{field: s}
   174  	return s
   175  }