github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/syllab/generator.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package syllab
     4  
     5  import (
     6  	"bytes"
     7  	"go/ast"
     8  	"go/parser"
     9  	"go/token"
    10  	"reflect"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"../assets"
    15  	"../log"
    16  )
    17  
    18  /*
    19  Before pass file to CompleteMethods(), dev must add needed methods to desire type by below template!
    20  Otherwise panic may occur due to improve performance we don't check some bad situation!!
    21  For just syllabDecoder() method you can omit syllabStackLen() & syllabLen()
    22  
    23  func ({{DesireName}} *{{DesireType}}) syllabDecoder(buf []byte) (err error) {
    24  	return
    25  }
    26  
    27  func ({{DesireName}} *{{DesireType}}) SyllabDecoder(buf []byte, stackIndex int) {
    28  	return
    29  }
    30  
    31  func ({{DesireName}} *{{DesireType}}) syllabEncoder(buf []byte) {}
    32  
    33  func ({{DesireName}} *{{DesireType}}) syllabEncoder() (buf []byte) {
    34  	buf = make([]byte, {{DesireName}}.syllabLen())
    35  	return
    36  }
    37  
    38  func ({{DesireName}} *{{DesireType}}) SyllabEncoder(buf []byte, stackIndex, heapIndex uint32) (hi uint32) {
    39  	return heapIndex
    40  }
    41  
    42  func ({{DesireName}} *{{DesireType}}) syllabStackLen() (ln uint32) {
    43  	return
    44  }
    45  
    46  func ({{DesireName}} *{{DesireType}}) syllabHeapLen() (ln uint32) {
    47  	return
    48  }
    49  
    50  func ({{DesireName}} *{{DesireType}}) syllabLen() (ln int) {
    51  	return int({{DesireName}}.SyllabStackLen() + {{DesireName}}.syllabHeapLen())
    52  }
    53  */
    54  
    55  // GenerationOptions indicate generator behavior!
    56  type GenerationOptions struct {
    57  	UnSafe      bool // true means don't copy data from given payload||buffer and just point to it for decoding fields! buffer can't GC until decoded struct free!
    58  	ForceUpdate bool // true means delete exiting codes and update encoders && decoders codes anyway!
    59  }
    60  
    61  // CompleteMethods use to update given go files and complete Syllab encoder&&decoder to any struct type in it!
    62  // It will overwrite given file methods! If you need it clone it before pass it here!
    63  func CompleteMethods(file *assets.File, gos *GenerationOptions) (err error) {
    64  	var fileSet *token.FileSet = token.NewFileSet()
    65  	var fileParsed *ast.File
    66  	fileParsed, err = parser.ParseFile(fileSet, "", file.Data, parser.ParseComments)
    67  	if err != nil {
    68  		return
    69  	}
    70  
    71  	var fileReplaces = make([]assets.ReplaceReq, 0, 4)
    72  	var sm = syllabMaker{
    73  		Options: gos,
    74  		Types:   map[string]*ast.TypeSpec{},
    75  	}
    76  
    77  	// find syllabDecoder || syllabEncoder method
    78  	for _, decl := range fileParsed.Decls {
    79  		switch d := decl.(type) {
    80  		case *ast.GenDecl:
    81  			for _, gDecl := range d.Specs {
    82  				switch gd := gDecl.(type) {
    83  				case *ast.TypeSpec:
    84  					sm.Types[gd.Name.Name] = gd
    85  				}
    86  			}
    87  		case *ast.FuncDecl:
    88  			if d.Recv != nil {
    89  				if sm.RN != d.Recv.List[0].Names[0].Name {
    90  					sm.reset()
    91  					sm.RN = d.Recv.List[0].Names[0].Name
    92  					sm.FRN = d.Recv.List[0].Names[0].Name + "."
    93  					sm.RTN = d.Recv.List[0].Type.(*ast.StarExpr).X.(*ast.Ident).Name
    94  
    95  					err = sm.make()
    96  					if err != nil {
    97  						return
    98  					}
    99  
   100  					sm.Encoder.WriteString("	return\n")
   101  					sm.Decoder.WriteString("	return\n")
   102  					sm.HeapSize.WriteString("	return\n")
   103  				}
   104  
   105  				// Just needed methods!
   106  				if d.Name.Name == "syllabDecoder" || d.Name.Name == "SyllabDecoder" {
   107  					fileReplaces = append(fileReplaces, assets.ReplaceReq{
   108  						Data:  sm.Decoder.String(),
   109  						Start: int(d.Body.Lbrace),
   110  						End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   111  				} else if d.Name.Name == "syllabEncoder" || d.Name.Name == "SyllabEncoder" {
   112  					fileReplaces = append(fileReplaces, assets.ReplaceReq{
   113  						Data:  sm.Encoder.String(),
   114  						Start: int(d.Body.Lbrace),
   115  						End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   116  				} else if d.Name.Name == "syllabStackLen" || d.Name.Name == "SyllabStackLen" {
   117  					fileReplaces = append(fileReplaces, assets.ReplaceReq{
   118  						Data: "\n	return " + sm.getSLIAsString(0) + "\n",
   119  						Start: int(d.Body.Lbrace),
   120  						End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   121  				} else if d.Name.Name == "syllabHeapLen" || d.Name.Name == "SyllabHeapLen" {
   122  					fileReplaces = append(fileReplaces, assets.ReplaceReq{
   123  						Data:  sm.HeapSize.String(),
   124  						Start: int(d.Body.Lbrace),
   125  						End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   126  				} else if d.Name.Name == "syllabLen" || d.Name.Name == "SyllabLen" {
   127  					fileReplaces = append(fileReplaces, assets.ReplaceReq{
   128  						Data: "\n	return int(" + sm.RN + ".syllabStackLen() + " + sm.RN + ".syllabHeapLen())\n",
   129  						Start: int(d.Body.Lbrace),
   130  						End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   131  				} else if strings.HasPrefix(d.Name.Name, "get") {
   132  					// TODO:::
   133  					// fileReplaces = append(fileReplaces, assets.ReplaceReq{
   134  					// 	Data: "\n	return " + sm.RN + ".syllabStackLen() + " + sm.RN + ".syllabHeapLen()\n",
   135  					// 	Start: int(d.Body.Lbrace),
   136  					// 	End:   int(d.Body.Rbrace) - 1}) // -1 to not remove end brace
   137  				}
   138  			}
   139  		}
   140  	}
   141  
   142  	file.Replace(fileReplaces)
   143  	file.State = assets.StateChanged
   144  	return
   145  }
   146  
   147  type syllabMaker struct {
   148  	Options   *GenerationOptions
   149  	Types     map[string]*ast.TypeSpec // All types
   150  	RN        string                   // Receiver Name
   151  	FRN       string                   // Flat Receiver Name e.g. req.Time.
   152  	RTN       string                   // Receiver Type Name
   153  	LSI       uint64                   // Last Stack Index
   154  	StackSize bytes.Buffer             // Stack len data to make slice size
   155  	HeapSize  bytes.Buffer             // Heap len data to make slice size
   156  	Encoder   bytes.Buffer             // Generated Data
   157  	Decoder   bytes.Buffer             // Generated Data
   158  }
   159  
   160  func (sm *syllabMaker) reset() {
   161  	sm.LSI = 0
   162  	sm.StackSize.Reset()
   163  	sm.HeapSize.Reset()
   164  	sm.Encoder.Reset()
   165  	sm.Decoder.Reset()
   166  }
   167  
   168  func (sm *syllabMaker) make() (err error) {
   169  	// Check needed type exist!!
   170  	typ, found := sm.Types[sm.RTN]
   171  	if !found {
   172  		return ErrSyllabNeededTypeNotExist
   173  	}
   174  
   175  	// Add some common data if ...
   176  	if sm.LSI == 0 {
   177  		sm.Decoder.WriteString(
   178  			"\n	var add, ln uint32\n	// var tempSlice []byte\n\n" +
   179  				"	if uint32(len(buf)) < " + sm.RN + ".syllabStackLen() {\n" +
   180  				"		err = syllab.ErrSyllabDecodeSmallSlice\n" +
   181  				"		return\n" +
   182  				"	}\n\n")
   183  
   184  		sm.Encoder.WriteString(
   185  			"\n	// buf = make([]byte, " + sm.RN + ".syllabLen()+offset)\n" +
   186  				"	var hsi uint32 = " + sm.RN + ".syllabStackLen() // Heap start index || Stack size!\n" +
   187  				"	// var i, ln uint32 // len of strings, slices, maps, ...\n\n")
   188  
   189  		sm.HeapSize.WriteString("\n")
   190  	}
   191  
   192  	var fieldName string
   193  	switch structType := typ.Type.(type) {
   194  	default:
   195  		// Just occur if bad file pass to generator!!
   196  		return
   197  	case *ast.BasicLit:
   198  		// TODO::: very simple type
   199  	case *ast.StructType:
   200  		for _, structField := range structType.Fields.List {
   201  			if structField.Tag != nil && sm.checkFieldTag(structField.Tag.Value) {
   202  				continue
   203  			}
   204  
   205  			for _, field := range structField.Names {
   206  				fieldName = field.Name
   207  
   208  				switch fieldType := structField.Type.(type) {
   209  				case *ast.FuncType, *ast.InterfaceType, *ast.ChanType:
   210  					log.Warn(ErrSyllabFieldType, fieldName)
   211  				case *ast.ArrayType:
   212  					// Check array is slice?
   213  					if fieldType.Len == nil {
   214  						// Slice generator
   215  						switch sliceType := fieldType.Elt.(type) {
   216  						case *ast.ArrayType:
   217  							// Check array is slice?
   218  							if fieldType.Len == nil {
   219  							} else {
   220  							}
   221  						case *ast.Ident:
   222  							switch sliceType.Name {
   223  							case "int", "uint":
   224  								log.Warn(ErrSyllabFieldType, fieldName)
   225  							case "bool":
   226  								if sm.Options.UnSafe {
   227  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetBoolArray(buf, " + sm.getSLIAsString(0) + ")\n")
   228  								} else {
   229  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetBoolArray(buf, " + sm.getSLIAsString(0) + ")\n")
   230  								}
   231  								sm.Encoder.WriteString("	hsi = syllab.SetBoolArray(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   232  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + "))\n")
   233  							case "byte", "uint8":
   234  								if sm.Options.UnSafe {
   235  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetByteArray(buf, " + sm.getSLIAsString(0) + ")\n")
   236  								} else {
   237  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetByteArray(buf, " + sm.getSLIAsString(0) + ")\n")
   238  								}
   239  								sm.Encoder.WriteString("	hsi = syllab.SetByteArray(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   240  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + "))\n")
   241  							case "int8":
   242  								if sm.Options.UnSafe {
   243  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetInt8Array(buf, " + sm.getSLIAsString(0) + ")\n")
   244  								} else {
   245  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt8Array(buf, " + sm.getSLIAsString(0) + ")\n")
   246  								}
   247  								sm.Encoder.WriteString("	hsi = syllab.SetInt8Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   248  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + "))\n")
   249  							case "uint16":
   250  								if sm.Options.UnSafe {
   251  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetUInt16Array(buf, " + sm.getSLIAsString(0) + ")\n")
   252  								} else {
   253  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt16Array(buf, " + sm.getSLIAsString(0) + ")\n")
   254  								}
   255  								sm.Encoder.WriteString("	hsi = syllab.SetUInt16Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   256  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + ") * 2)\n")
   257  							case "int16":
   258  								if sm.Options.UnSafe {
   259  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetInt16Array(buf, " + sm.getSLIAsString(0) + ")\n")
   260  								} else {
   261  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt16Array(buf, " + sm.getSLIAsString(0) + ")\n")
   262  								}
   263  								sm.Encoder.WriteString("	hsi = syllab.SetInt16Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   264  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + ") * 2)\n")
   265  							case "uint32":
   266  								if sm.Options.UnSafe {
   267  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetUInt32Array(buf, " + sm.getSLIAsString(0) + ")\n")
   268  								} else {
   269  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt32Array(buf, " + sm.getSLIAsString(0) + ")\n")
   270  								}
   271  								sm.Encoder.WriteString("	hsi = syllab.SetUInt32Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   272  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + ") * 4)\n")
   273  							case "int32":
   274  								if sm.Options.UnSafe {
   275  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetInt32Array(buf, " + sm.getSLIAsString(0) + ")\n")
   276  								} else {
   277  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt32Array(buf, " + sm.getSLIAsString(0) + ")\n")
   278  								}
   279  								sm.Encoder.WriteString("	hsi = syllab.SetInt32Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   280  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + ") * 4)\n")
   281  							case "uint64":
   282  								if sm.Options.UnSafe {
   283  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetUInt64Array(buf, " + sm.getSLIAsString(0) + ")\n")
   284  								} else {
   285  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt64Array(buf, " + sm.getSLIAsString(0) + ")\n")
   286  								}
   287  								sm.Encoder.WriteString("	hsi = syllab.SetUInt64Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   288  							case "int64":
   289  								if sm.Options.UnSafe {
   290  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetInt64Array(buf, " + sm.getSLIAsString(0) + ")\n")
   291  								} else {
   292  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt64Array(buf, " + sm.getSLIAsString(0) + ")\n")
   293  								}
   294  								sm.Encoder.WriteString("	hsi = syllab.SetInt64Array(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   295  								sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + ") * 8)\n")
   296  							case "string":
   297  								if sm.Options.UnSafe {
   298  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeStringArray(buf, " + sm.getSLIAsString(0) + ")\n")
   299  								} else {
   300  									sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetStringArray(buf, " + sm.getSLIAsString(0) + ")\n")
   301  								}
   302  								sm.Encoder.WriteString("	hsi = syllab.SetStringArray(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   303  								sm.HeapSize.WriteString("	for i:=0; i<len(" + sm.FRN + fieldName + "); i++ {\n")
   304  								sm.HeapSize.WriteString("		ln += uint32(len(" + sm.FRN + fieldName + "[i]))\n")
   305  								sm.HeapSize.WriteString("	}\n")
   306  							default:
   307  								// TODO::: get related type by its name as t.Elt.(*ast.Ident).Name
   308  								// sm.Encoder.WriteString("	syllab.SetUInt32(buf, " + sm.getSLIAsString(0) + ", hsi)\n")
   309  								// sm.Encoder.WriteString("	syllab.SetUInt32(buf, " + sm.getSLIAsString(4) + ", ln)\n")
   310  								// sm.Encoder.WriteString("	copy(buf[hsi:], " + sm.FRN + fieldName + ")\n")
   311  								// if sm.Options.UnSafe {
   312  								// 	sm.Decoder.WriteString("	add = syllab.GetUInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   313  								// 	sm.Decoder.WriteString("	ln = syllab.GetUInt32(buf, " + sm.getSLIAsString(4) + ")\n")
   314  								// 	sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = buf[add : add+ln]\n")
   315  								// } else {
   316  								// 	sm.Decoder.WriteString("	add = syllab.GetUInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   317  								// 	sm.Decoder.WriteString("	ln = syllab.GetUInt32(buf, " + sm.getSLIAsString(4) + ")\n")
   318  								// 	sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = make([]byte, ln)\n")
   319  								// 	sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + ", buf[add : add+ln])\n")
   320  								// }
   321  							}
   322  						}
   323  						// In any case we need 8 byte for address and len of array!
   324  						sm.LSI += 8
   325  					} else {
   326  						// Get array len
   327  						var ln, err = strconv.ParseUint(fieldType.Len.(*ast.BasicLit).Value, 10, 64)
   328  						if err != nil {
   329  							return ErrSyllabArrayLen
   330  						}
   331  
   332  						switch arrayType := fieldType.Elt.(type) {
   333  						case *ast.BasicLit:
   334  							if arrayType.Kind == token.STRING {
   335  								// Its common to use const to indicate number of array like in IP type as [16]byte!
   336  								// TODO::: get related const value by its name as t.Len.(*ast.BasicLit).Value
   337  							}
   338  						case *ast.ArrayType:
   339  							// Check array is slice?
   340  							if fieldType.Len == nil {
   341  							} else {
   342  							}
   343  						case *ast.Ident:
   344  							switch arrayType.Name {
   345  							case "int", "uint":
   346  								log.Warn(ErrSyllabFieldType, fieldName)
   347  							case "bool":
   348  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeBoolSliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   349  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToBoolSlice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   350  								sm.LSI += ln
   351  							case "byte", "uint8":
   352  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], " + sm.FRN + fieldName + "[:])\n")
   353  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], buf[" + sm.getSLIAsString(0) + ":])\n")
   354  								sm.LSI += ln
   355  							case "int8":
   356  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeInt8SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   357  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToInt8Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   358  								sm.LSI += ln
   359  							case "uint16":
   360  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeUInt16SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   361  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToUInt16Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   362  								sm.LSI += ln * 2
   363  							case "int16":
   364  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeInt16SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   365  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToInt16Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   366  								sm.LSI += ln * 2
   367  							case "uint32":
   368  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeUInt32SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   369  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToUInt32Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   370  								sm.LSI += ln * 4
   371  							case "int32":
   372  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeInt32SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   373  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToInt32Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   374  								sm.LSI += ln * 4
   375  							case "uint64":
   376  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeUInt64SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   377  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToUInt64Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   378  								sm.LSI += ln * 8
   379  							case "int64":
   380  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeInt64SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   381  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToInt64Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   382  								sm.LSI += ln * 8
   383  							case "float32":
   384  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeFloat32SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   385  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToFloat32Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   386  								sm.LSI += ln * 4
   387  							case "float64":
   388  								sm.Encoder.WriteString("	copy(buf[" + sm.getSLIAsString(0) + ":], convert.UnsafeFloat64SliceToByteSlice(" + sm.FRN + fieldName + "[:]))\n")
   389  								sm.Decoder.WriteString("	copy(" + sm.FRN + fieldName + "[:], convert.UnsafeByteSliceToFloat64Slice(buf[" + sm.getSLIAsString(0) + ":]))\n")
   390  								sm.LSI += ln * 4
   391  							case "string":
   392  								if sm.Options.UnSafe {
   393  									// sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeStringArray(buf, " + sm.getSLIAsString(0) + ")\n")
   394  								} else {
   395  									// sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetStringArray(buf, " + sm.getSLIAsString(0) + ")\n")
   396  								}
   397  								sm.Encoder.WriteString("	hsi = syllab.SetStringArray(buf, " + sm.FRN + fieldName + "[:], " + sm.getSLIAsString(0) + ", hsi)\n")
   398  								sm.HeapSize.WriteString("	for i:=0; i<" + fieldType.Len.(*ast.BasicLit).Value + "; i++ {\n")
   399  								sm.HeapSize.WriteString("		ln += len(" + sm.FRN + fieldName + "[i])\n")
   400  								sm.HeapSize.WriteString("	}\n")
   401  							default:
   402  								// TODO::: get related type by its name as fieldType.Elt.(*ast.Ident).Name
   403  							}
   404  						}
   405  					}
   406  				case *ast.StructType:
   407  					var tmp = sm.FRN
   408  					sm.FRN += fieldName + "."
   409  					sm.RTN = fieldType.Fields.List[0].Names[0].Name
   410  					// TODO::: add struct itself to sm.Types
   411  					err = sm.make()
   412  					sm.FRN = tmp
   413  				case *ast.MapType:
   414  
   415  				case *ast.Ident:
   416  					switch fieldType.Name {
   417  					case "int", "uint":
   418  						log.Warn(ErrSyllabFieldType, fieldName)
   419  					case "bool":
   420  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   421  						sm.Encoder.WriteString("	syllab.SetBool(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   422  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetBool(buf, " + sm.getSLIAsString(0) + ")\n")
   423  						sm.LSI++
   424  					case "byte":
   425  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   426  						sm.Encoder.WriteString("	syllab.SetByte(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   427  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetByte(buf, " + sm.getSLIAsString(0) + ")\n")
   428  						sm.LSI++
   429  					case "int8":
   430  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   431  						sm.Encoder.WriteString("	syllab.SetInt8(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   432  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt8(buf, " + sm.getSLIAsString(0) + ")\n")
   433  						sm.LSI++
   434  					case "uint8":
   435  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   436  						sm.Encoder.WriteString("	syllab.SetUInt8(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   437  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt8(buf, " + sm.getSLIAsString(0) + ")\n")
   438  						sm.LSI++
   439  					case "int16":
   440  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   441  						sm.Encoder.WriteString("	syllab.SetInt16(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   442  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt16(buf, " + sm.getSLIAsString(0) + ")\n")
   443  						sm.LSI += 2
   444  					case "uint16":
   445  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   446  						sm.Encoder.WriteString("	syllab.SetUInt16(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   447  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt16(buf, " + sm.getSLIAsString(0) + ")\n")
   448  						sm.LSI += 2
   449  					case "int32":
   450  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   451  						sm.Encoder.WriteString("	syllab.SetInt32(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   452  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   453  						sm.LSI += 4
   454  					case "uint32":
   455  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   456  						sm.Encoder.WriteString("	syllab.SetUInt32(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   457  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   458  						sm.LSI += 4
   459  					case "int64":
   460  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   461  						sm.Encoder.WriteString("	syllab.SetInt64(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   462  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetInt64(buf, " + sm.getSLIAsString(0) + ")\n")
   463  						sm.LSI += 8
   464  					case "uint64":
   465  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   466  						sm.Encoder.WriteString("	syllab.SetUInt64(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   467  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetUInt64(buf, " + sm.getSLIAsString(0) + ")\n")
   468  						sm.LSI += 8
   469  					case "float32":
   470  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   471  						sm.Encoder.WriteString("	syllab.SetFloat32(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   472  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetFloat32(buf, " + sm.getSLIAsString(0) + ")\n")
   473  						sm.LSI += 4
   474  					case "float64":
   475  						// Inlined by go compiler! So don't respect dev wants not use HelperFuncs
   476  						sm.Encoder.WriteString("	syllab.SetFloat64(buf, " + sm.getSLIAsString(0) + ", " + sm.FRN + fieldName + ")\n")
   477  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetFloat64(buf, " + sm.getSLIAsString(0) + ")\n")
   478  						sm.LSI += 8
   479  					case "string":
   480  						if sm.Options.UnSafe {
   481  							sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.UnsafeGetString(buf, " + sm.getSLIAsString(0) + ")\n")
   482  						} else {
   483  							sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = syllab.GetString(buf, " + sm.getSLIAsString(0) + ")\n")
   484  						}
   485  						sm.Encoder.WriteString("	hsi = syllab.SetString(buf, " + sm.FRN + fieldName + ", " + sm.getSLIAsString(0) + ", hsi)\n")
   486  						sm.HeapSize.WriteString("	ln += uint32(len(" + sm.FRN + fieldName + "))\n")
   487  						sm.LSI += 8
   488  					default:
   489  						// TODO::: below code not work for very simple type e.g. type test uint8
   490  						sm.Encoder.WriteString("	hsi = " + sm.FRN + fieldName + ".syllabEncoder(buf, " + sm.getSLIAsString(0) + ", hsi)\n")
   491  						sm.Decoder.WriteString("	" + sm.FRN + fieldName + ".syllabDecoder(buf, " + sm.getSLIAsString(0) + ")\n")
   492  
   493  						sm.StackSize.WriteString(" +" + sm.FRN + fieldName + ".syllabStackLen()")
   494  						sm.HeapSize.WriteString("	ln += " + sm.FRN + fieldName + ".syllabHeapLen()\n")
   495  					}
   496  				case *ast.SelectorExpr:
   497  					sm.Encoder.WriteString("	hsi = " + sm.FRN + fieldName + ".SyllabEncoder(buf, " + sm.getSLIAsString(0) + ", hsi)\n")
   498  					sm.Decoder.WriteString("	" + sm.FRN + fieldName + ".SyllabDecoder(buf," + sm.getSLIAsString(0) + ")\n")
   499  
   500  					sm.StackSize.WriteString(" + " + sm.FRN + fieldName + ".SyllabStackLen()")
   501  					sm.HeapSize.WriteString("	ln += " + sm.FRN + fieldName + ".SyllabHeapLen()\n")
   502  				case *ast.BasicLit:
   503  					// log.Info("BasicLit :", t.Kind)
   504  					// sm.Encoder.WriteString("	syllab.SetUInt32(buf, " + sm.getSLIAsString(0) + ", hsi)\n")
   505  					// sm.Encoder.WriteString("	syllab.SetUInt32(buf, " + sm.getSLIAsString(4) + ", ln)\n")
   506  					// sm.Encoder.WriteString("	copy(buf[hsi:], " + sm.FRN + fieldName + ")\n")
   507  					// if sm.Options.UnSafe {
   508  					// 	sm.Decoder.WriteString("	add = syllab.GetUInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   509  					// 	sm.Decoder.WriteString("	ln = syllab.GetUInt32(buf, " + sm.getSLIAsString(4) + ")\n")
   510  					// 	sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = convert.UnsafeByteSliceToString(buf[add : add+ln])\n")
   511  					// } else {
   512  					// 	sm.Decoder.WriteString("	add = syllab.GetUInt32(buf, " + sm.getSLIAsString(0) + ")\n")
   513  					// 	sm.Decoder.WriteString("	ln = syllab.GetUInt32(buf, " + sm.getSLIAsString(4) + ")\n")
   514  					// 	sm.Decoder.WriteString("	" + sm.FRN + fieldName + " = string(buf[add : add+ln])\n")
   515  					// }
   516  				}
   517  			}
   518  		}
   519  	}
   520  	return
   521  }
   522  
   523  func (sm *syllabMaker) getSLIAsString(plus uint64) (s string) {
   524  	// TODO::: Improve below line!
   525  	s += strconv.FormatUint(sm.LSI+plus, 10)
   526  	s += sm.StackSize.String()
   527  	return
   528  }
   529  
   530  func (sm *syllabMaker) checkFieldTag(tagValue string) (notInclude bool) {
   531  	var structFieldTag = reflect.StructTag(tagValue[1 : len(tagValue)-1])
   532  	var structFieldTagSyllab = structFieldTag.Get("syllab")
   533  	if structFieldTagSyllab == "-" {
   534  		return true
   535  	}
   536  	return
   537  }