<|start_filename|>stress/init_test.go<|end_filename|>
package stress

import (
	"math"
	"math/rand"
	"strings"
	"time"
)

var testSize = 80
var intSlice = make([]int, testSize)
var uintSlice = make([]uint, testSize)
var int64Slice = make([]int64, testSize)
var uint64slice = make([]uint64, testSize)
var uint32Slice = make([]uint32, testSize)
var uint16Slice = make([]uint16, testSize)
var int32Slice = make([]int32, testSize)
var int16Slice = make([]int16, testSize)
var uint8Slice = make([]uint8, testSize)
var int8Slice = make([]int8, testSize)
var float64Slice = make([]float64, testSize)
var float32Slice = make([]float32, testSize)
var stringSlice = make([]string, testSize)

func init() {
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < len(intSlice); i++ {
		intSlice[i] = int(rand.Int31())
	}
	for i := 0; i < len(uint64slice); i++ {
		uintSlice[i] = uint(rand.Uint32())
	}
	for i := 0; i < len(uint64slice); i++ {
		int64Slice[i] = rand.Int63()
	}
	for i := 0; i < len(uint64slice); i++ {
		uint64slice[i] = rand.Uint64()
	}
	for i := 0; i < len(uint32Slice); i++ {
		uint32Slice[i] = rand.Uint32()
	}
	for i := 0; i < len(uint32Slice); i++ {
		int32Slice[i] = int32(rand.Uint32())
	}
	for i := 0; i < len(uint16Slice); i++ {
		uint16Slice[i] = uint16(rand.Uint32() % math.MaxUint16)
	}
	for i := 0; i < len(int16Slice); i++ {
		int16Slice[i] = int16(rand.Uint32() % math.MaxUint16)
	}
	for i := 0; i < len(uint8Slice); i++ {
		uint8Slice[i] = uint8(rand.Uint32() % math.MaxInt8)
	}
	for i := 0; i < len(int8Slice); i++ {
		int8Slice[i] = int8(rand.Uint32() % math.MaxInt8)
	}
	for i := 0; i < len(float32Slice); i++ {
		float32Slice[i] = rand.Float32()
	}
	for i := 0; i < len(float64Slice); i++ {
		float64Slice[i] = float64(rand.Float32())
	}
	for i := 0; i < len(stringSlice); i++ {
		stringSlice[i] = strings.Repeat(string([]byte{33 + uint8(rand.Uint32()%10)}), 1+int(rand.Uint32()%10))
	}
}


<|start_filename|>unmarshaler.go<|end_filename|>
package bintly

var readers = NewReaders()

//Unmarshal converts []byte to e pointer or error
func Unmarshal(data []byte, v interface{}) error {
	stream := readers.Get()
	defer readers.Put(stream)
	return UnmarshalStream(stream, data, v)
}

//UnmarshalStream converts []byte to e pointer or error
func UnmarshalStream(stream *Reader, data []byte, v interface{}) error {
	err := stream.FromBytes(data)
	if err != nil {
		return err
	}
	err = stream.Any(v)
	if err != nil {
		return err
	}

	return nil
}




//Decode converts []byte to decoder or error
func Decode(data []byte, coder Decoder) error {
	stream := readers.Get()
	err := stream.FromBytes(data)
	if err != nil {
		return err
	}
	if err = stream.Coder(coder);err == nil {
		readers.Put(stream)
	}
	return err
}

<|start_filename|>codegen/cmd/cli.go<|end_filename|>
package cmd

import (
	"github.com/jessevdk/go-flags"
	"github.com/viant/bintly/codegen"
	"log"
)

//RunClient validates CLI options and triggers code generator
func RunClient(Version string, args []string) int {
	options := &codegen.Options{}
	_, err := flags.ParseArgs(options, args)
	if err != nil {
		log.Fatal(err)
		return 1
	}
	err = options.Validate()
	if err != nil {
		log.Printf("validation eror: %v", err)
		return 1
	}
	err = codegen.Generate(options)
	if err != nil {
		log.Printf("code generation error %v", err)
		return 1
	}
	return 0
}


<|start_filename|>bintly/gen.go<|end_filename|>
package main

import (
	"github.com/viant/bintly/codegen/cmd"
	"os"
)

var Version string = "1.0"

func main() {
	//args := []string{
	//	"main","-s=/xxx/message.go", "-d=/xxx","-t=Message",
	//}

	args := os.Args
	cmd.RunClient(Version, args)
}


<|start_filename|>doc.go<|end_filename|>
// Package bintly defines binary coding and encoding using native golang numeric data type representation.
package bintly


<|start_filename|>coder_test.go<|end_filename|>
package bintly

import (
	"github.com/stretchr/testify/assert"
	"reflect"
	"testing"
)

func TestStructCoder_DecodeBinary(t *testing.T) {
	type Foo struct {
		ID   int
		Name string
	}
	type intAlias int
	ia := intAlias(3023)

	var (
		useCases = []struct {
			description string
			value       interface{}
		}{
			{
				description: "int/uint types",
				value: struct {
					I   int
					U   uint
					Is  []int
					Uis []uint
				}{1, 2, intSlice, uintSlice},
			},
			{
				description: "int64/uint64 types",
				value: struct {
					I int64
					U uint64
				}{1000, 3000},
			},
			{
				description: "int32/uint32 types",
				value: struct {
					I int32
					U uint32
				}{-1500, 30777},
			},
			{
				description: "int16/uint16 types",
				value: struct {
					I int16
					U uint16
				}{-1544, 664},
			},
			{
				description: "int16/uint16 types",
				value: struct {
					I int16
					U uint16
				}{-15, 255},
			},
			{
				description: "float64/float32 types",
				value: struct {
					F1 float64
					F2 float32
				}{0.1, 3.222},
			},
			{
				description: "bool type",
				value: struct {
					B    bool
					BPtr *bool
				}{true, &boolSlice[0]},
			},
			{
				description: "alias type",
				value: struct {
					I     intAlias
					Bytes []byte
					X     *intAlias
					Y     []intAlias
					Z     []*intAlias
				}{102, []byte("123"), &ia, []intAlias{1, 2, 3}, []*intAlias{&ia}},
			},
			{
				description: "anonymous type",
				value: struct {
					Foo
					Items []Foo
				}{Foo: Foo{1, "name"}, Items: []Foo{{10, "test"}}},
			},
			{
				description: "map[string]int type",
				value: struct {
					M map[string]int
					Z map[int]intAlias
				}{map[string]int{
					"k1": 1,
					"k2": 2,
				}, nil},
			},
			{
				description: "nil slice",
				value: struct {
					A []intAlias
					B []intAlias
				}{[]intAlias{1, 2}, nil},
			},
			{
				description: "nil struct",
				value: struct {
					A *Foo
					B *Foo
				}{A: &Foo{}, B: nil},
			},
		}
	)

	for _, useCase := range useCases {
		data, err := Marshal(useCase.value)
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		actualPtr := reflect.New(reflect.TypeOf(useCase.value))
		err = Unmarshal(data, actualPtr.Interface())
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		assert.EqualValues(t, useCase.value, actualPtr.Elem().Interface(), useCase.description)

	}

}

func Test_CustomSlice(t *testing.T) {
	var aSlice = customSlice{"a", "b", "c"}
	data, err := Marshal(&aSlice)
	assert.Nil(t, err)
	var clone customSlice
	err = Unmarshal(data, &clone)
	assert.Nil(t, err)
	assert.EqualValues(t, clone, aSlice)
}

type customSlice []string

//DecodeBinary decodes data to binary stream
func (e *customSlice) DecodeBinary(stream *Reader) error {
	size := int(stream.Alloc())
	if size == NilSize {
		return nil
	}
	*e = make([]string, size)
	for i := 0; i < size; i++ {
		item := ""
		stream.String(&item)
		(*e)[i] = item
	}
	return nil
}

//EncodeBinary encodes data from binary stream
func (e *customSlice) EncodeBinary(stream *Writer) error {
	if *e == nil {
		stream.Alloc(NilSize)
		return nil
	}
	stream.Alloc(int32(len(*e)))
	for i := range *e {
		stream.String((*e)[i])
	}
	return nil
}


func Test_CustomMap(t *testing.T) {
	var aMap = customMap{"a": []uint32{1, 2}, "b": []uint32{2, 3}, "c": []uint32{3, 4}}
	data, err := Marshal(&aMap)
	assert.Nil(t, err)
	var clone customMap
	err = Unmarshal(data, &clone)
	assert.Nil(t, err)
	assert.EqualValues(t, clone, aMap)
}

type customMap map[string][]uint32

//DecodeBinary decodes data to binary stream
func (e *customMap) DecodeBinary(stream *Reader) error {
	size := int(stream.Alloc())
	if size == NilSize {
		return nil
	}
	*e = make(map[string][]uint32, size)
	for i := 0; i < size; i++ {
		var key string
		var val []uint32
		stream.MString(&key)
		stream.MUint32s(&val)
		(*e)[key] = val
	}
	return nil
}

//EncodeBinary encodes data from binary stream
func (e *customMap) EncodeBinary(stream *Writer) error {
	if *e == nil {
		stream.Alloc(NilSize)
		return nil
	}
	stream.Alloc(int32(len(*e)))
	for k, v := range *e {
		stream.MString(k)
		stream.MUint32s(v)
	}
	return nil
}


<|start_filename|>codegen/test_data/slices/message.go<|end_filename|>
package slices

type SubMessage struct {
	Id   int
	Name string
}

//type SubMessage2 []SubMessage


type Message struct {
	M1 []SubMessage
//	M2 []*SubMessage
	//M3 SubMessages
	//M4 *SubMessages
//	SubMessage2
//	SubMessages2
}


<|start_filename|>int_test.go<|end_filename|>
package bintly

import (
	"encoding/binary"
	"github.com/stretchr/testify/assert"
	"math"
	"math/rand"
	"testing"
)

func TestPutInt(t *testing.T) {
	var useCases = []struct {
		description string
		i           int
	}{
		{
			description: "max uint64",
			i:           math.MaxUint32,
		},
		{
			description: "min uint64",
			i:           0,
		},
		{
			description: "random uint64",
			i:           int(rand.Uint64()),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutInt(data, useCase.i)
		actual := Int(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetInt(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}
}

func TestPutUint(t *testing.T) {
	var useCases = []struct {
		description string
		i           uint
	}{
		{
			description: "max uint64",
			i:           math.MaxUint32,
		},
		{
			description: "min uint64",
			i:           0,
		},
		{
			description: "random uint64",
			i:           uint(rand.Uint32()),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutUint(data, useCase.i)
		actual := Uint(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetUint(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}
}

func TestPutUint64(t *testing.T) {
	var useCases = []struct {
		description string
		i           uint64
	}{
		{
			description: "max uint64",
			i:           math.MaxUint64,
		},
		{
			description: "min uint64",
			i:           0,
		},
		{
			description: "random uint64",
			i:           rand.Uint64(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutUint64(data, useCase.i)
		actual := Uint64(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetUint64(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func BenchmarkPutUint64(b *testing.B) {
	var bs = make([]byte, 8)
	for i := 0; i < b.N; i++ {
		for _, j := range uint64slice {
			PutUint64(bs, j)
			a := Uint64(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func BenchmarkPutUint64_Binary(b *testing.B) {
	coder := binary.LittleEndian
	var bs = make([]byte, 8)
	for i := 0; i < b.N; i++ {
		for _, j := range uint64slice {
			coder.PutUint64(bs, j)
			a := coder.Uint64(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func TestPutUint32(t *testing.T) {
	var useCases = []struct {
		description string
		i           uint32
	}{
		{
			description: "max uint32",
			i:           math.MaxUint32,
		},
		{
			description: "min uint32",
			i:           0,
		},
		{
			description: "random uint32",
			i:           rand.Uint32(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 4)
		PutUint32(data, useCase.i)
		actual := Uint32(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetUint32(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func BenchmarkPutUint32(b *testing.B) {
	var bs = make([]byte, 4)
	for i := 0; i < b.N; i++ {
		for _, j := range uint32Slice {
			PutUint32(bs, j)
			a := Uint32(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func BenchmarkPutUint32_Binary(b *testing.B) {
	coder := binary.LittleEndian
	var bs = make([]byte, 16)
	for i := 0; i < b.N; i++ {
		for _, j := range uint32Slice {
			coder.PutUint32(bs, j)
			a := coder.Uint32(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func TestPutUint16(t *testing.T) {
	var useCases = []struct {
		description string
		i           uint16
	}{
		{
			description: "max uint16",
			i:           math.MaxUint16,
		},
		{
			description: "min uint16",
			i:           0,
		},
		{
			description: "random uint16",
			i:           uint16(rand.Uint32() % math.MaxUint16),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 4)
		PutUint16(data, useCase.i)
		actual := Uint16(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetUint16(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func BenchmarkPutUint16(b *testing.B) {
	var bs = make([]byte, 4)
	for i := 0; i < b.N; i++ {
		for _, j := range uint16Slice {
			PutUint16(bs, j)
			a := Uint16(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func BenchmarkPutUint16_Binary(b *testing.B) {
	coder := binary.LittleEndian
	var bs = make([]byte, 16)
	for i := 0; i < b.N; i++ {
		for _, j := range uint16Slice {
			coder.PutUint16(bs, j)
			a := coder.Uint16(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func TestPutInt64(t *testing.T) {
	var useCases = []struct {
		description string
		i           int64
	}{
		{
			description: "max int64",
			i:           math.MaxInt64,
		},
		{
			description: "min int64",
			i:           0,
		},
		{
			description: "random int64",
			i:           rand.Int63(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutInt64(data, useCase.i)
		actual := Int64(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetInt64(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}
}

func Benchmark_Int64(b *testing.B) {
	var data = make([]byte, 8)
	expect := int64Slice[0]
	PutInt64(data, expect)
	for i := 0; i < b.N; i++ {
		actual := Int64(data)
		if actual != expect {
			assert.EqualValues(b, expect, actual)
		}
	}
}

func Benchmark_GetInt64(b *testing.B) {
	var data = make([]byte, 8)
	expect := int64Slice[0]
	PutInt64(data, expect)
	var actual int64
	for i := 0; i < b.N; i++ {
		GetInt64(data, &actual)
		if actual != expect {
			assert.EqualValues(b, expect, actual)
		}
	}

}

func TestPutInt32(t *testing.T) {
	var useCases = []struct {
		description string
		i           int32
	}{
		{
			description: "max int32",
			i:           math.MaxInt32,
		},
		{
			description: "min int32",
			i:           0,
		},
		{
			description: "random int32",
			i:           rand.Int31(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 4)
		PutInt32(data, useCase.i)
		actual := Int32(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetInt32(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func TestPutInt16(t *testing.T) {
	var useCases = []struct {
		description string
		i           int16
	}{
		{
			description: "max int16",
			i:           math.MaxInt16,
		},
		{
			description: "min int16",
			i:           0,
		},
		{
			description: "random int16",
			i:           int16(rand.Int31() % math.MaxInt16),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 4)
		PutInt16(data, useCase.i)
		actual := Int16(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
		actual = 0
		GetInt16(data, &actual)
		assert.EqualValues(t, useCase.i, actual, useCase.description)

	}

}


<|start_filename|>unsafe.go<|end_filename|>
package bintly

import "unsafe"

func unsafeGetBytes(s string) []byte {
	return *(*[]byte)(unsafe.Pointer(&s))
}

func unsafeGetString(bs []byte) string {
	if len(bs) == 0 {
		return ""
	}
	return *(*string)(unsafe.Pointer(&bs))
}


<|start_filename|>marshaler.go<|end_filename|>
package bintly

var writers = NewWriters()

//Marshal converts e into []byte, or error
func Marshal(v interface{}) ([]byte, error) {
	stream := writers.Get()
	defer writers.Put(stream)
	return MarshalStream(stream, v)
}

//MarshalStream converts e into []byte, or error
func MarshalStream(stream *Writer, v interface{}) ([]byte, error) {
	err := stream.Any(v)
	if err != nil {
		return nil, err
	}
	bs := stream.Bytes()
	return bs, nil
}




//Encode converts encoder into []byte, or error
func Encode(coder Encoder) ([]byte, error) {
	stream := writers.Get()
	err := stream.Coder(coder)
	if err != nil {
		return nil, err
	}
	bs := stream.Bytes()
	writers.Put(stream)
	return bs, nil
}


<|start_filename|>binary/writer.go<|end_filename|>
package binary

import (
	"bytes"
	"encoding/binary"
	"math"
)

//Writer represents binary writer
type Writer struct {
	bytes.Buffer
	buf   []byte
	coder binary.ByteOrder
}

//Alloc returns allocated size
func (b *Writer) Alloc(size uint32) error {
	b.coder.PutUint32(b.buf, size)
	_, err := b.Write(b.buf[:4])
	return err
}

//Int writes an int
func (b *Writer) Int(v int) error {
	b.coder.PutUint64(b.buf, uint64(v))
	_, err := b.Write(b.buf[:8])
	return err
}

//Int32 writes an int32
func (b *Writer) Int32(v int32) error {
	b.coder.PutUint32(b.buf, uint32(v))
	_, err := b.Write(b.buf[:4])
	return err
}

//Bool writes byte
func (b *Writer) Bool(v bool) error {
	bt := []byte{0}
	if v {
		bt[0] = 1
	}
	_, err := b.Write(bt)
	return err
}

//Ints writes []int
func (b *Writer) Ints(v []int) error {
	if err := b.Alloc(uint32(len(v))); err != nil {
		return err
	}
	for _, i := range v {
		if err := b.Int(i); err != nil {
			return err
		}
	}
	return nil
}

//String writes string v
func (b *Writer) String(v string) error {
	if err := b.Alloc(uint32(len(v))); err != nil {
		return err
	}
	_, err := b.Write([]byte(v))
	return err
}

//Strings writes []string
func (b *Writer) Strings(vs []string) error {
	if err := b.Alloc(uint32(len(vs))); err != nil {
		return err
	}
	for _, s := range vs {
		if err := b.String(s); err != nil {
			return err
		}
	}
	return nil
}

func (b *Writer) ToBytes() []byte {
	return b.Buffer.Bytes()
}

//Bytes writes bytes
func (b *Writer) Bytes(v []byte) error {
	if err := b.Alloc(uint32(len(v))); err != nil {
		return err
	}
	_, err := b.Write(v)
	return err
}

//Float64 writes float64
func (b *Writer) Float64(v float64) error {
	bits := math.Float64bits(v)
	b.coder.PutUint64(b.buf, bits)
	_, err := b.Write(b.buf[:8])
	return err
}

//Float64s writes float64
func (b *Writer) Float64s(v []float64) error {
	if err := b.Alloc(uint32(len(v))); err != nil {
		return err
	}
	for _, i := range v {
		b.coder.PutUint64(b.buf, uint64(i))
		bits := math.Float64bits(i)
		b.coder.PutUint64(b.buf, bits)
		if _, err := b.Write(b.buf[:8]); err != nil {
			return err
		}
	}
	return nil
}

//NewWriter creates a binary writer
func NewWriter(coder binary.ByteOrder) *Writer {
	return &Writer{
		coder: coder,
		buf:   make([]byte, 8),
	}
}


<|start_filename|>binary/reader.go<|end_filename|>
package binary

import (
	"encoding/binary"
	"math"
)

//Reader represents binary reader
type Reader struct {
	data   []byte
	offset int
	coder  binary.ByteOrder
}

//Alloc returns allocation size
func (b *Reader) Alloc() uint32 {
	alloc := b.coder.Uint32(b.data[b.offset:])
	b.offset += 4
	return alloc
}

//Int returns int
func (b *Reader) Int() int {
	v := b.coder.Uint64(b.data[b.offset:])
	b.offset += 8
	return int(v)
}

//Ints returns []int
func (b *Reader) Ints() []int {
	size := b.Alloc()
	var result = make([]int, size)
	for i := 0; i < int(size); i++ {
		result[i] = b.Int()
	}
	return result
}

//Int32 writes an int32
func (b *Reader) Int32() int32 {
	v := b.coder.Uint32(b.data[b.offset:])
	b.offset += 4
	return int32(v)
}

//Bool return bool
func (b *Reader) Bool() bool {
	result := b.data[b.offset] == 1
	b.offset++
	return result
}

//String returns string
func (b *Reader) String() string {
	size := int(b.Alloc())
	result := string(b.data[b.offset : b.offset+size])
	b.offset += size
	return result
}

//Bytes returns bytes
func (b *Reader) Bytes() []byte {
	size := int(b.Alloc())
	result := b.data[b.offset : b.offset+size]
	b.offset += size
	return result
}

//Strings returns []string
func (b *Reader) Strings() []string {
	size := int(b.Alloc())
	var result = make([]string, size)
	for i := 0; i < size; i++ {
		result[i] = b.String()
	}
	return result
}

//Float64 returns float64
func (b *Reader) Float64() float64 {
	bits := uint64(b.Int())
	return math.Float64frombits(bits)
}

//Float64s returns []float64
func (b *Reader) Float64s() []float64 {
	size := int(b.Alloc())
	var result = make([]float64, size)
	for i := 0; i < size; i++ {
		result[i] = b.Float64()
	}
	return result
}

//NewReader creates a reader
func NewReader(data []byte, coder binary.ByteOrder) *Reader {
	return &Reader{
		data:  data,
		coder: coder,
	}
}


<|start_filename|>stress/run_test.go<|end_filename|>
package stress

import (
	"bytes"
	"encoding/gob"
	"encoding/json"
	"github.com/fxamacker/cbor"
	"github.com/stretchr/testify/assert"
	"github.com/viant/bintly"
	"github.com/vmihailenco/msgpack"
	"math"
	"testing"
)


var b1 = BenchStruct{
	A1: math.MaxInt32,
	A2: "this is benchmark test",
	A3: true,
	A4: 3.3333,
	A5: intSlice,
	A6: stringSlice,
	A7: float64Slice,
	A8: uint8Slice,
}

func Test_BenchStruct(t *testing.T) {

	{ //test custom binary
		data, err := b1.ToBytes()
		assert.Nil(t, err)
		clone := BenchStruct{}
		clone.FromBytes(data)
		assert.EqualValues(t, clone, b1)
	}
	{ //test custom bintly
		data, err := bintly.Marshal(&b1)
		assert.Nil(t, err)
		clone := BenchStruct{}
		err = bintly.Unmarshal(data, &clone)
		assert.EqualValues(t, clone, b1)
	}
	{ //test bintly reflect
		alias := BenchStructAlias(b1)
		data, err := bintly.Marshal(&alias)
		assert.Nil(t, err)
		clone := BenchStructAlias{}
		err = bintly.Unmarshal(data, &clone)
		assert.EqualValues(t, clone, alias)
	}
	{ //test gob
		var buf bytes.Buffer
		dec := gob.NewDecoder(&buf)
		enc := gob.NewEncoder(&buf)
		err := enc.Encode(&b1)
		assert.Nil(t, err)
		clone := BenchStruct{}
		err = dec.Decode(&clone)
		assert.Nil(t, err)
		assert.EqualValues(t, b1, clone)
	}
	{ //test cobr reflect
		alias := BenchStructAlias(b1)
		data, err := cbor.Marshal(&alias, cbor.EncOptions{})
		assert.Nil(t, err)
		clone := BenchStructAlias{}
		err = cbor.Unmarshal(data, &clone)
		assert.EqualValues(t, clone, b1)
	}

}

func BenchmarkUnmarshalBintly(b *testing.B) {
	data, err := bintly.Marshal(&b1)
	assert.Nil(b, err)
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		err = bintly.Unmarshal(data, &c1)
	}
	assert.Nil(b, err)
}

func BenchmarkMarshalBintly(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		_, _ = bintly.Marshal(b1)
	}
}

func BenchmarkUnmarshalBintlyReflect(b *testing.B) {
	var a1 = BenchStructAlias(b1)
	data, err := bintly.Marshal(&a1)
	assert.Nil(b, err)
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		var b1 BenchStructAlias
		err = bintly.Unmarshal(data, &b1)

	}
	assert.Nil(b, err)
}

func BenchmarkMarshalBintlyReflect(b *testing.B) {
	var a1 = BenchStructAlias(b1)
	b.ResetTimer()
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		_, err = bintly.Marshal(&a1)
	}
	assert.Nil(b, err)
}

func BenchmarkUnmarshalBinary(b *testing.B) {
	data, _ := b1.ToBytes()
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		c1.FromBytes(data)
	}
}

func BenchmarkMarshalBinary(b *testing.B) {
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		_, err = b1.ToBytes()
	}
	assert.Nil(b, err)
}

func BenchmarkUnMarshalGob(b *testing.B) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(b1)
	if err != nil {
		assert.NotNil(b, err)
	}
	data := buf.Bytes()
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		dec := gob.NewDecoder(bytes.NewReader(data))
		err = dec.Decode(&c1)

	}
	assert.Nil(b, err, err)
}

func BenchmarkMarshalGob(b *testing.B) {
	var buf bytes.Buffer
	b.ResetTimer()
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		enc := gob.NewEncoder(&buf)
		err = enc.Encode(b1)

	}
	assert.Nil(b, err)
}

func BenchmarkUnmarshalCbor(b *testing.B) {
	data, err := cbor.Marshal(b1, cbor.EncOptions{})
	if !assert.Nil(b, err) {
		return
	}
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		err = cbor.Unmarshal(data, &c1)
	}
	assert.Nil(b, err)
}

func BenchmarkMarshalCbor(b *testing.B) {
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		_, err = cbor.Marshal(b1,cbor.EncOptions{})
	}
	assert.Nil(b, err)
}

func BenchmarkUnmarshalMsgPack(b *testing.B) {
	data, err := msgpack.Marshal(b1)
	if !assert.Nil(b, err) {
		return
	}
	b.ResetTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		err = msgpack.Unmarshal(data, &c1)
	}
	assert.Nil(b, err)
}

func BenchmarkMarshalMsgPack(b *testing.B) {
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		_, err = msgpack.Marshal(b1)
	}
	assert.Nil(b, err)
}

func BenchmarkJSONUnmarshal(b *testing.B) {
	data, err := json.Marshal(b1)
	assert.Nil(b, err)
	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		c1 := BenchStruct{}
		err = json.Unmarshal(data, &c1)
	}
	assert.Nil(b, err)

}
func BenchmarkJSONMarshal(b *testing.B) {
	b.ReportAllocs()
	var err error
	for i := 0; i < b.N; i++ {
		_, err = json.Marshal(b1)
	}
	assert.Nil(b, err)
}


<|start_filename|>codegen/test_data/messages/message.go<|end_filename|>
package messages

type SubMessage struct {
	Id   int
	Name string
}

type Message struct {
	//M1 SubMessage
	//M2 *SubMessage
	SubMessage
}


<|start_filename|>codegen/generator.go<|end_filename|>
package codegen

import (
	"fmt"
	"github.com/viant/toolbox"
	"io/ioutil"
	"strings"
)

type fieldGenerator func(session *session, field *toolbox.FieldInfo) (string, error)

//templateParameters represents template variables
type templateParameters struct {
	Method             string
	Field              string
	FieldType          string
	ReceiverAlias      string
	TransientVar       string
	BaseType           string
	PointerNeeded      bool
	KeyFieldType       string
	ValueFieldType     string
	KeyMethod          string
	ValueMethod        string
	PointerMethod      bool
	BaseValueFieldType string
}

//Generate generates transformed code into  output file
func Generate(options *Options) error {
	session := newSession(options)
	session.addImport("github.com/viant/bintly")
	err := session.readPackageCode()
	if err != nil {
		return err
	}

	// then we generate code for the types given
	for _, rootType := range options.Types {
		if err := generateStructCoding(session, rootType); err != nil {
			return err
		}
	}

	prefix, err := expandBlockTemplate(fileCode, struct {
		Pkg     string
		Code    string
		Imports string
	}{session.pkg, "", session.getImports()})
	if err != nil {
		return err
	}

	dest := session.Dest
	err = ioutil.WriteFile(dest, []byte(prefix+strings.Join(session.structCodingCode, "")), 0644)
	session.structCodingCode = []string{}
	return err

}

//generateStructCoding creates encoder and decoder for given type
func generateStructCoding(session *session, typeName string) error {
	if ok := session.shallGenerateCode(typeName); !ok {
		return nil
	}
	enc, err := generateStructEncoding(session, typeName)
	if err != nil {
		return err
	}
	dec, err := generateStructDecoding(session, typeName)
	if err != nil {
		return err
	}
	receiver := strings.ToLower(typeName[0:1]) + " *" + typeName
	code, err := expandBlockTemplate(codingStructType, struct {
		Receiver      string
		EncodingCases string
		DecodingCases string
	}{receiver, enc, dec})
	if err != nil {
		return err
	}
	session.structCodingCode = append(session.structCodingCode, code)
	return nil
}

//generateStructEncoding creates encoder code
func generateStructEncoding(sess *session, typeName string) (string, error) {
	return generateCoding(sess, typeName, false, func(sess *session, field *toolbox.FieldInfo) (string, error) {
		return "", fmt.Errorf("unsupported type: %s for field %v.%v", field.TypeName, typeName, field.Name)
	})
}

//generateStructDecoding creates decoder code
func generateStructDecoding(sess *session, typeName string) (string, error) {
	return generateCoding(sess, typeName, true, func(session *session, field *toolbox.FieldInfo) (string, error) {
		return "", fmt.Errorf("unsupported type: %s for field %v.%v", field.TypeName, typeName, field.Name)
	})

}

//generateCoding generates field template codes for each type
func generateCoding(sess *session, typeName string, isDecoder bool, fn fieldGenerator) (string, error) {
	baseTemplate := encodeBaseType
	derivedTemplate := encodeDerivedBaseType
	baseSliceTemplate := encodeBaseSliceType
	derivedSliceTemplate := encodeCustomSliceType
	structTemplate := encodeStructType
	customSliceTemplate := encodeSliceStructType
	enbeddedAliasSliceTemplate := encodeEmbeddedAliasTemplate
	baseMapTemplate := encodeBasicMapTemplate
	baseSliceMapTemplate := encodeSliceMapTemplate
	if isDecoder {
		baseTemplate = decodeBaseType
		derivedTemplate = decodeDerivedBaseType
		baseSliceTemplate = decodeBaseSliceType
		derivedSliceTemplate = decodeCustomSliceType
		structTemplate = decodeStructType
		customSliceTemplate = decodeSliceStructType
		enbeddedAliasSliceTemplate = decodeEmbeddedAliasSliceTemplate
		baseMapTemplate = decodeBasicMapTemplate
		baseSliceMapTemplate = decodeSliceMapTemplate
	}
	typeInfo := sess.Type(typeName)
	if typeInfo == nil {
		return "", fmt.Errorf("failed to lookup '%s'", typeName)
	}
	var codings = make([]string, 0)
	fields := typeInfo.Fields()
	for _, field := range fields {
		receiverAlias := strings.ToLower(typeName[0:1])
		var generated bool
		var err error

		// base type
		if generated, err = generateBaseType(field, baseTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// derived type
		if generated, err = generateDerivedType(sess, field, derivedTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// base slice type
		if generated, err = generateBaseSliceType(sess, field, baseSliceTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}
		// derived slice type
		if generated, err = generateDerivedSliceType(sess, field, derivedSliceTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}

		if generated {
			continue
		}

		// struct type
		if generated, err = generateStructType(sess, field, structTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// struct slice
		if generated, err = generateSliceOfStruct(sess, field, customSliceTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// slice alias
		if generated, err = generateSliceAlias(sess, field, enbeddedAliasSliceTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// base map
		if generated, err = generateMap(sess, field, baseMapTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// base map with slice value
		if generated, err = generateMapWithSlice(sess, field, baseSliceMapTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}

		// embedded map
		if generated, err = generateEmbeddedMapType(sess, field, baseMapTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}
		//embedded map slice
		if generated, err = generateEmbeddedMapSliceType(sess, field, baseSliceMapTemplate, receiverAlias, &codings); err != nil {
			return "", err
		}
		if generated {
			continue
		}
		code, err := fn(sess, field)
		if err != nil {
			return "", err
		}
		codings = append(codings, code)
	}
	return strings.Join(codings, "\n"), nil
}

//generateEmbeddedMapSliceType generates code for embedded type of map with slice value types
func generateEmbeddedMapSliceType(sess *session, field *toolbox.FieldInfo, templateId int, alias string, codings *[]string) (bool, error) {
	fieldType := sess.Type(field.TypeName)
	if fieldType == nil {
		return false, nil
	}
	if !fieldType.IsMap {
		return false, nil
	}
	fValueTypeName := fieldType.ValueTypeName
	keyMethod := getMapMethod(fieldType.KeyTypeName)
	isPointer := isPointer(fValueTypeName)
	pointerToSlice := isPointerToSlice(fValueTypeName)
	if fValueTypeName[0:2] == "[]" {
		fieldValueTypeName := getBaseFieldTypeName(fValueTypeName)
		valueFieldType := sess.Type(fieldValueTypeName)
		if valueFieldType == nil {
			return false, nil
		}
		if err := generateStructCoding(sess, fieldValueTypeName); err != nil {
			return false, err
		}
		code, err := expandFieldTemplate(templateId, templateParameters{
			KeyMethod: keyMethod,
			//ValueMethod: valueMethod,
			ValueMethod:        "Coder",
			KeyFieldType:       fieldType.KeyTypeName,
			ValueFieldType:     fieldType.ValueTypeName,
			Field:              fieldType.Name,
			ReceiverAlias:      alias,
			PointerNeeded:      !isPointer,
			PointerMethod:      pointerToSlice,
			BaseValueFieldType: fieldValueTypeName,
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil

	}
	return false, nil
}

//generateEmbeddedMapType generates code for embedded type of map with basic value types
func generateEmbeddedMapType(sess *session, field *toolbox.FieldInfo, templateId int, alias string, codings *[]string) (bool, error) {
	fieldType := sess.Type(field.TypeName)
	if fieldType == nil {
		return false, nil
	}
	if !fieldType.IsMap {
		return false, nil
	}
	keyMethod := getMapMethod(fieldType.KeyTypeName)
	isPointer := isPointer(fieldType.ValueTypeName)
	valueFieldType := sess.Type(fieldType.ValueTypeName)
	if valueFieldType != nil && fieldType.ValueTypeName[0:2] != "[]" {

		if err := generateStructCoding(sess, valueFieldType.Name); err != nil {
			return false, err
		}
		code, err := expandFieldTemplate(templateId, templateParameters{
			KeyMethod: keyMethod,
			//ValueMethod: valueMethod,
			ValueMethod:        "Coder",
			KeyFieldType:       fieldType.KeyTypeName,
			ValueFieldType:     fieldType.ValueTypeName,
			Field:              fieldType.Name,
			ReceiverAlias:      alias,
			PointerNeeded:      !isPointer,
			BaseValueFieldType: valueFieldType.Name,
			PointerMethod:      strings.Contains(field.ValueTypeName, "*") || strings.Contains(fieldType.ValueTypeName, "*"),
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil
	}
	return false, nil
}

//generateMapWithSlice generates code for basic map of slice value type
func generateMapWithSlice(sess *session, field *toolbox.FieldInfo, templateId int, alias string, codings *[]string) (bool, error) {
	// case with ValueFieldType is nil
	if !field.IsMap {
		return false, nil
	}
	keyMethod := getMapMethod(field.KeyTypeName)
	isPointer := strings.Contains(field.ValueTypeName, "*")
	pointerToSlice := strings.Contains(field.ValueTypeName, "[]*")
	// no session type info for field type
	fieldValueTypeName := field.ValueTypeName
	if fieldValueTypeName[0:2] == "[]" {
		fieldValueTypeName = getBaseFieldTypeName(fieldValueTypeName)
	}
	if err := generateStructCoding(sess, fieldValueTypeName); err != nil {
		return false, err
	}
	code, err := expandFieldTemplate(templateId, templateParameters{
		KeyMethod: keyMethod,
		//ValueMethod: valueMethod,
		ValueMethod:        "Coder",
		KeyFieldType:       field.KeyTypeName,
		ValueFieldType:     field.ValueTypeName,
		Field:              field.Name,
		ReceiverAlias:      alias,
		PointerNeeded:      !isPointer,
		PointerMethod:      pointerToSlice,
		BaseValueFieldType: fieldValueTypeName,
	})
	if err != nil {
		return false, err
	}
	*codings = append(*codings, code)
	return true, nil

}

//generateMap generates code for basic map of primitive value type
func generateMap(sess *session, field *toolbox.FieldInfo, templateId int, receiverAlias string, codings *[]string) (bool, error) {
	if !field.IsMap {
		return false, nil
	}
	keyMethod := getMapMethod(field.KeyTypeName)
	isPointer := strings.Contains(field.ValueTypeName, "*")
	valueFieldType := sess.Type(field.ValueTypeName)
	if valueFieldType != nil && field.ValueTypeName[0:2] != "[]" {
		if err := generateStructCoding(sess, valueFieldType.Name); err != nil {
			return false, err
		}
		code, err := expandFieldTemplate(templateId, templateParameters{
			KeyMethod: keyMethod,
			//ValueMethod: valueMethod,
			ValueMethod:        "Coder",
			KeyFieldType:       field.KeyTypeName,
			ValueFieldType:     field.ValueTypeName,
			Field:              field.Name,
			ReceiverAlias:      receiverAlias,
			PointerNeeded:      !isPointer,
			BaseValueFieldType: valueFieldType.Name,
			PointerMethod:      strings.Contains(field.ValueTypeName, "*"),
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil
	}
	return false, nil
}

//generateMap generates code for embedded slice alias
func generateSliceAlias(sess *session, field *toolbox.FieldInfo, templateId int, receiverAlias string, codings *[]string) (bool, error) {
	fieldType := sess.Type(field.TypeName)
	if fieldType == nil {
		return false, nil
	}
	if fieldType.IsSlice && !isInlineSliceType(field.TypeName) {
		if err := generateStructCoding(sess, fieldType.ComponentType); err != nil {
			return false, err
		}
		var code string
		err := generateSliceCoding(sess, field.TypeName, fieldType.IsPointerComponentType, fieldType.ComponentType)
		if err != nil {
			return false, err
		}
		code, err = expandFieldTemplate(templateId, templateParameters{
			Method:        "Coder",
			Field:         field.Name,
			ReceiverAlias: receiverAlias,
			PointerNeeded: !field.IsPointer,
			FieldType:     field.TypeName,
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil
	}
	return false, nil
}

//generateSliceCoding generates code for basic slice type
func generateSliceCoding(sess *session, typeName string, isPointer bool, componentType string) error {
	if ok := sess.shallGenerateCode(typeName); !ok {
		return nil
	}
	code, err := expandBlockTemplate(codingSliceType, struct {
		ReceiverAlias string
		SliceType     string
		IsPointer     bool
		ComponentType string
	}{
		ReceiverAlias: strings.ToLower(typeName[0:1]),
		SliceType:     typeName,
		IsPointer:     isPointer,
		ComponentType: componentType,
	})
	if err != nil {
		return err
	}
	sess.structCodingCode = append(sess.structCodingCode, code)
	return nil
}

//generateSliceOfStruct generates code for slice of struct type
func generateSliceOfStruct(sess *session, field *toolbox.FieldInfo, customSliceTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	if field.IsSlice && isInlineSliceType(field.TypeName) {
		if err := generateStructCoding(sess, field.ComponentType); err != nil {
			return false, err
		}
		fieldTypeName := field.ComponentType
		code, err := expandFieldTemplate(customSliceTemplate, templateParameters{
			Method:        "Coder",
			Field:         field.Name,
			FieldType:     fieldTypeName,
			ReceiverAlias: receiverAlias,
			TransientVar:  toolbox.ToCaseFormat(field.Name, toolbox.CaseUpperCamel, toolbox.CaseLowerCamel),
			PointerNeeded: !field.IsPointerComponent,
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil
	}
	return false, nil
}

//generateStructType generates struct type code
func generateStructType(sess *session, field *toolbox.FieldInfo, structTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	fieldType := sess.Type(getBaseFieldType(field.TypeName))
	if fieldType == nil {
		return false, nil
	}
	if isStruct(fieldType) && !field.IsSlice && !field.IsMap && !field.IsPointerComponent {
		if err := generateStructCoding(sess, fieldType.Name); err != nil {
			return false, err
		}
		code, err := expandFieldTemplate(structTemplate, templateParameters{
			Method:        "Coder",
			Field:         field.Name,
			FieldType:     field.TypeName,
			ReceiverAlias: receiverAlias,
			PointerNeeded: !field.IsPointer,
		})
		if err != nil {
			return false, err
		}
		*codings = append(*codings, code)
		return true, nil
	}
	return false, nil
}

//generateDerivedSliceType generates derived slice types code
func generateDerivedSliceType(sess *session, field *toolbox.FieldInfo, derivedSliceTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	customSliceType, err := getDerivedSliceType(sess, field.TypeName)
	if customSliceType == "" {
		return false, nil
	}
	sess.addImport("unsafe")
	method := genCodingMethod("[]"+customSliceType, false, true)
	code, err := expandFieldTemplate(derivedSliceTemplate, templateParameters{
		Method:        method,
		Field:         field.Name,
		FieldType:     field.TypeName,
		ReceiverAlias: receiverAlias,
		TransientVar:  toolbox.ToCaseFormat(field.Name, toolbox.CaseUpperCamel, toolbox.CaseLowerCamel),
		BaseType:      customSliceType,
	})
	if err != nil {
		return false, err
	}
	*codings = append(*codings, code)
	return true, nil
}

//generateBaseSliceType generates base slice types code
func generateBaseSliceType(sess *session, field *toolbox.FieldInfo, baseSliceTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	sliceType, err := getBaseSliceType(sess, field.TypeName)
	if sliceType == "" {
		return false, nil
	}
	method := genCodingMethod("[]"+sliceType, false, true)
	code, err := expandFieldTemplate(baseSliceTemplate, templateParameters{
		Method:        method,
		Field:         field.Name,
		FieldType:     field.TypeName,
		ReceiverAlias: receiverAlias,
		TransientVar:  toolbox.ToCaseFormat(field.Name, toolbox.CaseUpperCamel, toolbox.CaseLowerCamel),
		BaseType:      sliceType,
	})
	if err != nil {
		return false, err
	}
	*codings = append(*codings, code)
	return true, nil
}

//generateDerivedType generates derived primitive types code
func generateDerivedType(sess *session, field *toolbox.FieldInfo, derivedTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	baseType, err := getBaseDerivedType(sess, field.TypeName)
	if baseType == "" {
		return false, nil
	}
	method := genCodingMethod(baseType, field.IsPointer, field.IsSlice)
	code, err := expandFieldTemplate(derivedTemplate, templateParameters{
		Method:        method,
		Field:         field.Name,
		FieldType:     field.TypeName,
		ReceiverAlias: receiverAlias,
		TransientVar:  toolbox.ToCaseFormat(field.Name, toolbox.CaseUpperCamel, toolbox.CaseLowerCamel),
		BaseType:      baseType,
	})
	if err != nil {
		return false, err
	}
	*codings = append(*codings, code)
	return true, nil
}

//generateBaseType generates base primitive type code
func generateBaseType(field *toolbox.FieldInfo, baseTemplate int, receiverAlias string, codings *[]string) (bool, error) {
	if !isBaseType(field.TypeName) {
		return false, nil
	}
	method := genCodingMethod(field.TypeName, field.IsPointer, field.IsSlice)
	code, err := expandFieldTemplate(baseTemplate, templateParameters{
		Method:        method,
		Field:         field.Name,
		ReceiverAlias: receiverAlias,
	})
	if err != nil {
		return false, err
	}
	*codings = append(*codings, code)
	return true, nil
}

//getBaseDerivedType finds base type for derived types
func getBaseDerivedType(s *session, typeName string) (string, error) {
	aType := s.Type(typeName)
	if aType == nil {
		return "", fmt.Errorf("alias type name %v is nil for type %v ", aType, typeName)
	}
	if aType.IsDerived {
		derived := aType.Derived
		if isBaseType(derived) {
			return derived, nil
		}
		derived, err := getBaseDerivedType(s, derived)
		if err != nil {
			return "", err
		}
		if isBaseType(derived) {
			return derived, nil
		}
	}
	return "", nil
}

//getBaseSliceType provides base type dervied type
func getBaseSliceType(s *session, typeName string) (string, error) {
	aType := s.Type(typeName)
	if aType == nil {
		return "", fmt.Errorf("alias type name %v is nil for type %v ", aType, typeName)
	}
	if aType.IsSlice && isBaseType(aType.ComponentType) {
		return aType.ComponentType, nil
	}
	return "", nil
}

//getDerivedSliceType provides base type for derived slice type
func getDerivedSliceType(s *session, typeName string) (string, error) {
	aType := s.Type(typeName)
	if aType == nil {
		return "", fmt.Errorf("alias type name %v is nil for type %v ", aType, typeName)
	}

	if aType.IsSlice {
		cType, err := getBaseDerivedType(s, aType.ComponentType)
		if err != nil {
			return "", fmt.Errorf("can't find base type %v for componentType %v ", aType, aType.ComponentType)
		}
		return cType, nil
	}
	return "", nil
}

//genCodingMethod provides coding method
func genCodingMethod(baseType string, IsPointer bool, IsSlice bool) string {
	if strings.Contains(baseType, "time.Time") {
		baseType = strings.Replace(baseType, "time.", "", 1)
	}
	codingMethod := strings.Title(baseType)
	if IsPointer {
		codingMethod += "Ptr"
	}
	if IsSlice {
		codingMethod = codingMethod[2:]
		codingMethod += "s"
	}
	return codingMethod

}

func getBaseFieldType(fieldType string) string {
	if !strings.Contains(fieldType, "[]") {
		return fieldType
	}
	if fieldType[0:3] == "[]*" {
		return fieldType[3:]
	}
	if fieldType[0:2] == "[]" {
		return fieldType[2:]
	}
	return fieldType
}

func getMapMethod(baseType string) string {
	var isPointer bool
	var isSlice bool
	if strings.Contains(baseType, "*") {
		baseType = strings.Replace(baseType, "*", "", 1)
		isPointer = true
	}
	if strings.Contains(baseType, "[]") {
		baseType = strings.Replace(baseType, "[]", "", 1)
		isSlice = true
	}

	codingMethod := strings.Title(baseType)
	if isPointer {
		codingMethod += "Ptr"
	}
	if isSlice {
		//codingMethod = codingMethod[2:]
		codingMethod += "s"
	}
	return codingMethod

}

func isInlineSliceType(fieldType string) bool {
	return strings.Contains(fieldType, "[]")
}

func getBaseFieldTypeName(fieldValueTypeName string) string {
	return strings.ReplaceAll(strings.ReplaceAll(fieldValueTypeName, "[]", ""), "*", "")
}

func isPointerToSlice(fValueTypeName string) bool {
	return strings.Contains(fValueTypeName, "[]*")
}

func isPointer(fValueTypeName string) bool {
	return strings.Contains(fValueTypeName, "*")
}


<|start_filename|>encoder.go<|end_filename|>
package bintly

//Encoder defines an encoder interface
type Encoder interface {
	//EncodeBinary writes data to the stream
	EncodeBinary(stream *Writer) error
}

//Alloc represents repeated type allocator
type Alloc interface {
	//Alloc returns size of repeated type
	Alloc() int32
}


<|start_filename|>marshaler_test.go<|end_filename|>
package bintly

import (
	"github.com/stretchr/testify/assert"
	"math"
	"reflect"
	"testing"
)

type marshStruct01 struct {
	ID          int
	OptionalID  *int
	Name        string
	Options     []string
	Elements    []int
	Coordinates []float64
}

func (m *marshStruct01) DecodeBinary(stream *Reader) error {
	stream.Int(&m.ID)
	stream.IntPtr(&m.OptionalID)
	stream.String(&m.Name)
	stream.Strings(&m.Options)
	stream.Ints(&m.Elements)
	stream.Float64s(&m.Coordinates)
	return nil
}

func (m *marshStruct01) EncodeBinary(stream *Writer) error {
	stream.Int(m.ID)
	stream.IntPtr(m.OptionalID)
	stream.String(m.Name)
	stream.Strings(m.Options)
	stream.Ints(m.Elements)
	stream.Float64s(m.Coordinates)
	return nil
}

type marshStruct02 struct {
	A1 int
	B1 *int
	C1 []int
	D1 uint
	E1 *uint
	F1 []uint

	A2 int64
	B2 *int64
	C2 []int64
	D2 uint64
	E2 *uint64
	F2 []uint64

	A3 int32
	B3 *int32
	C3 []int32
	D3 uint32
	E3 *uint32
	F3 []uint32

	A4 int16
	B4 *int16
	C4 []int16
	D4 uint16
	E4 *uint16
	F4 []uint16
	A5 int8
	B5 *int8
	C5 []int8
	D5 uint8
	E5 *uint8
	F5 []uint8
	G  bool
	H  string
}

func (m *marshStruct02) EncodeBinary(stream *Writer) error {
	stream.Int(m.A1)
	stream.IntPtr(m.B1)
	stream.Ints(m.C1)
	stream.Uint(m.D1)
	stream.UintPtr(m.E1)
	stream.Uints(m.F1)

	stream.Int64(m.A2)
	stream.Int64Ptr(m.B2)
	stream.Int64s(m.C2)
	stream.Uint64(m.D2)
	stream.Uint64Ptr(m.E2)
	stream.Uint64s(m.F2)

	stream.Int32(m.A3)
	stream.Int32Ptr(m.B3)
	stream.Int32s(m.C3)
	stream.Uint32(m.D3)
	stream.Uint32Ptr(m.E3)
	stream.Uint32s(m.F3)

	stream.Int16(m.A4)
	stream.Int16Ptr(m.B4)
	stream.Int16s(m.C4)
	stream.Uint16(m.D4)
	stream.Uint16Ptr(m.E4)
	stream.Uint16s(m.F4)

	stream.Int8(m.A5)
	stream.Int8Ptr(m.B5)
	stream.Int8s(m.C5)
	stream.Uint8(m.D5)
	stream.Uint8Ptr(m.E5)
	stream.Uint8s(m.F5)
	stream.Bool(m.G)
	stream.String(m.H)
	return nil
}

func (m *marshStruct02) DecodeBinary(stream *Reader) error {
	stream.Int(&m.A1)
	stream.IntPtr(&m.B1)
	stream.Ints(&m.C1)
	stream.Uint(&m.D1)
	stream.UintPtr(&m.E1)
	stream.Uints(&m.F1)

	stream.Int64(&m.A2)
	stream.Int64Ptr(&m.B2)
	stream.Int64s(&m.C2)
	stream.Uint64(&m.D2)
	stream.Uint64Ptr(&m.E2)
	stream.Uint64s(&m.F2)

	stream.Int32(&m.A3)
	stream.Int32Ptr(&m.B3)
	stream.Int32s(&m.C3)
	stream.Uint32(&m.D3)
	stream.Uint32Ptr(&m.E3)
	stream.Uint32s(&m.F3)

	stream.Int16(&m.A4)
	stream.Int16Ptr(&m.B4)
	stream.Int16s(&m.C4)
	stream.Uint16(&m.D4)
	stream.Uint16Ptr(&m.E4)
	stream.Uint16s(&m.F4)

	stream.Int8(&m.A5)
	stream.Int8Ptr(&m.B5)
	stream.Int8s(&m.C5)
	stream.Uint8(&m.D5)
	stream.Uint8Ptr(&m.E5)
	stream.Uint8s(&m.F5)
	stream.Bool(&m.G)
	stream.String(&m.H)
	return nil
}

func TestMarshal(t *testing.T) {

	var useCases = []struct {
		description string
		source      interface{}
	}{
		{
			description: "basic struct",
			source: &marshStruct01{
				ID:   100,
				Name: "<NAME>",
				Options: []string{
					"1",
					"20",
					"300",
				},
				Elements:    []int{30, 40, 50, 100, 1000, 2000},
				Coordinates: []float64{1.2, 0.2, 5.3, 6.3},
			},
		},
		{
			description: "large struct",
			source: &marshStruct02{
				A1: 101,
				B1: &intSlice[0],
				C1: intSlice,
				D1: 201,
				E1: &uintSlice[0],
				F1: uintSlice,
				A2: math.MinInt32,
				B2: &int64Slice[0],
				C2: int64Slice,
				D2: uint64slice[0],
				E2: &uint64slice[0],
				F2: uint64slice,
				A3: int32Slice[0],
				B3: &int32Slice[0],
				C3: int32Slice,
				D3: uint32Slice[0],
				E3: &uint32Slice[0],
				F3: uint32Slice,
				A4: 0,
				B4: nil,
				C4: nil,
				D4: uint16Slice[0],
				E4: &uint16Slice[0],
				F4: uint16Slice,
				A5: int8Slice[0],
				B5: &int8Slice[0],
				C5: int8Slice,
				D5: uint8Slice[0],
				E5: &uint8Slice[0],
				F5: uint8Slice,
				G:  false,
				H:  "test me",
			},
		},
	}

	for _, useCase := range useCases {
		data, err := Marshal(useCase.source)
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		var actual interface{}
		vType := reflect.TypeOf(useCase.source)
		if vType.Kind() == reflect.Ptr {
			vType = vType.Elem()
		}
		actual = reflect.New(vType).Interface()
		err = Unmarshal(data, actual)
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		assert.EqualValues(t, useCase.source, actual, useCase.description)
	}
}


<|start_filename|>writer.go<|end_filename|>
package bintly

import (
	"fmt"
	"github.com/viant/bintly/conv"
	"reflect"
	"sync"
	"time"
)

type (
	//Writer represents binary writer
	Writer struct {
		alloc  encInt32s
		mAlloc encUint16s
		encInts
		encUints
		encInt64s
		encUint64s
		encInt32s
		encUint32s
		encInt16s
		encUint16s
		encInt8s
		encUint8s
		encFloat64s
		encFloat32s
	}

	encInts     []int
	encUints    []uint
	encInt64s   []int64
	encUint64s  []uint64
	encInt32s   []int32
	encUint32s  []uint32
	encInt16s   []int16
	encUint16s  []uint16
	encInt8s    []int8
	encUint8s   []uint8
	encFloat64s []float64
	encFloat32s []float32
)

//Any writes any supported writer type
func (w *Writer) Any(v interface{}) error {
	switch actual := v.(type) {
	case int:
		w.Int(actual)
	case *int:
		w.IntPtr(actual)
	case []int:
		w.Ints(actual)
	case uint:
		w.Uint(actual)
	case *uint:
		w.UintPtr(actual)
	case []uint:
		w.Uints(actual)
	case int64:
		w.Int64(actual)
	case *int64:
		w.Int64Ptr(actual)
	case []int64:
		w.Int64s(actual)
	case uint64:
		w.Uint64(actual)
	case *uint64:
		w.Uint64Ptr(actual)
	case []uint64:
		w.Uint64s(actual)
	case int32:
		w.Int32(actual)
	case *int32:
		w.Int32Ptr(actual)
	case []int32:
		w.Int32s(actual)
	case uint32:
		w.Uint32(actual)
	case *uint32:
		w.Uint32Ptr(actual)
	case []uint32:
		w.Uint32s(actual)
	case int16:
		w.Int16(actual)
	case *int16:
		w.Int16Ptr(actual)
	case []int16:
		w.Int16s(actual)
	case uint16:
		w.Uint16(actual)
	case *uint16:
		w.Uint16Ptr(actual)
	case []uint16:
		w.Uint16s(actual)
	case int8:
		w.Int8(actual)
	case *int8:
		w.Int8Ptr(actual)
	case []int8:
		w.Int8s(actual)
	case uint8:
		w.Uint8(actual)
	case *uint8:
		w.Uint8Ptr(actual)
	case []uint8:
		w.Uint8s(actual)
	case float64:
		w.Float64(actual)
	case *float64:
		w.Float64Ptr(actual)
	case []float64:
		w.Float64s(actual)
	case float32:
		w.Float32(actual)
	case *float32:
		w.Float32Ptr(actual)
	case []float32:
		w.Float32s(actual)
	case bool:
		w.Bool(actual)
	case *bool:
		w.BoolPtr(actual)
	case []bool:
		w.Bools(actual)

	case string:
		w.String(actual)
	case *string:
		w.StringPtr(actual)
	case []string:
		w.Strings(actual)
	case time.Time:
		w.Time(actual)
	case *time.Time:
		w.TimePtr(actual)
	default:
		encoder, ok := v.(Encoder)
		if ok {
			return w.Coder(encoder)
		}
		return w.anyReflect(v)
	}
	return nil
}

func (w *Writer) anyReflect(v interface{}) error {

	value := reflect.ValueOf(v)
	rawType := reflect.TypeOf(v)
	isPointer := rawType.Kind() == reflect.Ptr
	if isPointer {
		rawType = rawType.Elem()
	}
	switch rawType.Kind() {
	case reflect.Struct:
		coder := structCoders.Get()
		defer structCoders.Put(coder)
		if err := coder.set(value, rawType); err != nil {
			return err
		}
		return w.Coder(coder)
	case reflect.Map:
		coder := mapCoders.Get()
		defer mapCoders.Put(coder)
		coder.set(value, rawType)
		return w.Coder(coder)
	case reflect.Slice:
		coder := sliceCoders.Get()
		defer sliceCoders.Put(coder)
		coder.set(value, rawType)
		return w.Coder(coder)

	//TODO add support for an arbitrary slice
	default:

		//handles natives type aliases
		if nativeType := conv.MatchNative(rawType); nativeType != nil {
			if isPointer {
				return w.Any(value.Elem().Convert(*nativeType).Interface())
			} else {
				return w.Any(value.Convert(*nativeType).Interface())
			}
		}

	}
	return fmt.Errorf("unsupproted writer type: %T", v)
}

//Alloc append data allocation size for repeater or pointers(0,1) types
func (w *Writer) Alloc(size int32) {
	w.alloc.Int32(size)
}

//Alloc append data allocation size for repeater or pointers(0,1) types
func (w *Writer) MAlloc(size uint16) {
	w.mAlloc.Uint16(size)
}

//IntPtr writes *int
func (w *Writer) IntPtr(v *int) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Int(*v)
}

//Ints writes []int
func (w *Writer) Ints(vs []int) {
	w.alloc.Int32(int32(len(vs)))
	w.appendInts(vs)
}

//MInts writes medium size slice []int
func (w *Writer) MInts(vs []int) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendInts(vs)
}

//UintPtr writes *uint
func (w *Writer) UintPtr(v *uint) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Uint(*v)
}

//Uints writes []uint
func (w *Writer) Uints(vs []uint) {
	w.alloc.Int32(int32(len(vs)))
	w.appendUints(vs)
}


//MUints writes []uint
func (w *Writer) MUints(vs []uint) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendUints(vs)
}

//Int64Ptr writes *int64
func (w *Writer) Int64Ptr(v *int64) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Int64(*v)
}

//Int64s writes []int64
func (w *Writer) Int64s(vs []int64) {
	w.alloc.Int32(int32(len(vs)))
	w.appendInt64s(vs)
}

//MInt64s writes []int64
func (w *Writer) MInt64s(vs []int64) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendInt64s(vs)
}

//Uint64Ptr writes *uint64
func (w *Writer) Uint64Ptr(v *uint64) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Uint64(*v)
}

//Uint64s writes []uint64
func (w *Writer) Uint64s(vs []uint64) {
	w.alloc.Int32(int32(len(vs)))
	w.appendUint64s(vs)
}

//MUint64s writes []uint64
func (w *Writer) MUint64s(vs []uint64) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendUint64s(vs)
}


//Int32Ptr writes *int32
func (w *Writer) Int32Ptr(v *int32) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Int32(*v)
}

//Int32s writes []int32
func (w *Writer) Int32s(vs []int32) {
	w.alloc.Int32(int32(len(vs)))
	w.appendInt32s(vs)
}

//MInt32s writes []int32
	func (w *Writer) MInt32s(vs []int32) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendInt32s(vs)
}


//Uint32Ptr writes *uint32
func (w *Writer) Uint32Ptr(v *uint32) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Uint32(*v)
}

//Uint32s writes []uint32
func (w *Writer) Uint32s(vs []uint32) {
	w.alloc.Int32(int32(len(vs)))
	w.appendUint32s(vs)
}

//MUint32s writes medium size slice (upto 64k) []uint32
func (w *Writer) MUint32s(vs []uint32) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendUint32s(vs)
}


//Int16Ptr writes *int16
func (w *Writer) Int16Ptr(v *int16) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Int16(*v)
}

//Int16s writes []int16
func (w *Writer) Int16s(vs []int16) {
	w.alloc.Int32(int32(len(vs)))
	w.appendInt16s(vs)
}

//Uint16Ptr writes *uint16
func (w *Writer) Uint16Ptr(v *uint16) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Uint16(*v)
}

//Uint16s writes []uint16
func (w *Writer) Uint16s(vs []uint16) {
	w.alloc.Int32(int32(len(vs)))
	w.appendUint16s(vs)
}

//Int8Ptr writes *int8
func (w *Writer) Int8Ptr(v *int8) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Int8(*v)
}

//Int8s writes []int8
func (w *Writer) Int8s(vs []int8) {
	w.alloc.Int32(int32(len(vs)))
	w.appendInt8s(vs)
}

//Uint8Ptr writes *uint8
func (w *Writer) Uint8Ptr(v *uint8) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Uint8(*v)
}

//Uint8s writes []uint8
func (w *Writer) Uint8s(vs []uint8) {
	w.alloc.Int32(int32(len(vs)))
	w.appendUint8s(vs)
}

//MUint8s writes medium (upto 64k) []uint8
func (w *Writer) MUint8s(vs []uint8) {
	w.mAlloc.Uint16(uint16(len(vs)))
	w.appendUint8s(vs)
}

//Float64Ptr writes *float64
func (w *Writer) Float64Ptr(v *float64) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Float64(*v)
}

//Float64s writes []float64
func (w *Writer) Float64s(vs []float64) {
	w.alloc.Int32(int32(len(vs)))
	w.appendFloat64s(vs)
}

//Float32Ptr writes *float32
func (w *Writer) Float32Ptr(v *float32) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	w.Float32(*v)
}

//Float32s writes []float32
func (w *Writer) Float32s(vs []float32) {
	w.alloc.Int32(int32(len(vs)))
	w.appendFloat32s(vs)
}

//Bool writes bool
func (w *Writer) Bool(v bool) {
	i := uint8(0)
	if v {
		i = 1
	}
	w.Uint8(i)
}

//BoolPtr writes *bool
func (w *Writer) BoolPtr(v *bool) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	i := uint8(0)
	if *v {
		i = 1
	}
	w.Uint8(i)
}

//Bools writes []bool
func (w *Writer) Bools(vs []bool) {
	w.alloc.Int32(int32(len(vs)))
	for _, b := range vs {
		i := uint8(0)
		if b {
			i = 1
		}
		w.Uint8(i)
	}
}

//String writes string
func (w *Writer) String(v string) {
	b := unsafeGetBytes(v)
	w.Uint8s(b)
}

//StringPtr writes *string
func (w *Writer) StringPtr(v *string) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	b := unsafeGetBytes(*v)
	w.Uint8s(b)
}

//Strings writes []string
func (w *Writer) Strings(v []string) {
	size := len(v)
	w.alloc.Int32(int32(size))
	for i := range v {
		w.String(v[i])
	}
}

//MString writes a medium (64k)  string
func (w *Writer) MString(v string) {
	b := unsafeGetBytes(v)
	w.MUint8s(b)
}

//MStringPtr writes medium *string
func (w *Writer) MStringPtr(v *string) {
	if v == nil {
		w.mAlloc.Uint16(0)
		return
	}
	b := unsafeGetBytes(*v)
	w.MUint8s(b)
}


//MStrings writes medium size (64k) []string
func (w *Writer) MStrings(v []string) {
	size := len(v)
	w.mAlloc.Uint16(uint16(size))
	for i := range v {
		w.MString(v[i])
	}
}

//Time writes time.Time
func (w *Writer) Time(v time.Time) {
	n := v.UnixNano()
	w.Int64(n)
}

//TimePtr writes *time.Time
func (w *Writer) TimePtr(v *time.Time) {
	if v == nil {
		w.alloc.Int32(0)
		return
	}
	w.alloc.Int32(1)
	n := v.UnixNano()
	w.Int64(n)
}

//Coder encodes data with encoder
func (w *Writer) Coder(v Encoder) error {

	if v == nil {
		w.alloc.Int32(0)
		return nil
	}
	size := int32(1)
	if allocator, ok := v.(Alloc); ok {
		size = allocator.Alloc()
	}

	w.alloc.Int32(size)
	switch size {
	case NilSize, 0:
		return nil
	case 1:
		return v.EncodeBinary(w)
	}
	for i := 0; i < int(size); i++ {
		if err := v.EncodeBinary(w); err != nil {
			return err
		}
	}
	return nil
}

//Size returns data size
func (w *Writer) Size() int {
	result := size8bitsInBytes + w.alloc.size()
	result += w.mAlloc.size()
	result += w.encInts.size() + w.encUints.size()
	result += w.encInt64s.size() + w.encUint64s.size()
	result += w.encInt32s.size() + w.encUint32s.size()
	result += w.encInt16s.size() + w.encUint16s.size()
	result += w.encInt8s.size() + w.encUint8s.size()
	result += w.encFloat64s.size() + w.encFloat32s.size()
	return result
}

//Bytes returns writer bytes and resets stream
func (w *Writer) Bytes() []byte {
	var data = make([]byte, w.Size())
	offset := 0
	var ok bool
	if offset, ok = w.alloc.store(data, offset, codecAlloc); ok {
		w.alloc = w.alloc[:0]
	}
	if offset, ok = w.mAlloc.store(data, offset, codecMAlloc); ok {
		w.mAlloc = w.mAlloc[:0]
	}
	if offset, ok = w.encInts.store(data, offset); ok {
		w.encInts = w.encInts[:0]
	}
	if offset, ok = w.encFloat64s.store(data, offset); ok {
		w.encFloat64s = w.encFloat64s[:0]
	}
	if offset, ok = w.encUint8s.store(data, offset); ok {
		w.encUint8s = w.encUint8s[:0]
	}
	if offset, ok = w.encInt32s.store(data, offset, codecInt32s); ok {
		w.encInt32s = w.encInt32s[:0]
	}
	if offset, ok = w.encUint32s.store(data, offset); ok {
		w.encUint32s = w.encUint32s[:0]
	}
	if offset, ok = w.encFloat32s.store(data, offset); ok {
		w.encFloat32s = w.encFloat32s[:0]
	}
	if offset, ok = w.encUints.store(data, offset); ok {
		w.encUints = w.encUints[:0]
	}
	if offset, ok = w.encInt64s.store(data, offset); ok {
		w.encInt64s = w.encInt64s[:0]
	}
	if offset, ok = w.encUint64s.store(data, offset); ok {
		w.encUint64s = w.encUint64s[:0]
	}

	if offset, ok = w.encInt16s.store(data, offset); ok {
		w.encInt16s = w.encInt16s[:0]
	}
	if offset, ok = w.encUint16s.store(data, offset, codecUint16s); ok {
		w.encUint16s = w.encUint16s[:0]
	}
	if offset, ok = w.encInt8s.store(data, offset); ok {
		w.encInt8s = w.encInt8s[:0]
	}
	data[offset] = codecEOF
	return data
}

//Int writes int
func (s *encInts) Int(v int) {
	*s = append(*s, v)
}

func (s *encInts) appendInts(vs []int) {
	*s = append(*s, vs...)
}

func (s *encInts) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecInts
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutInts(data[offset:], *s)
	offset += sizeIntInBytes * size
	return offset, true
}

func (s *encInts) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * sizeIntInBytes)
	}
	return 0
}

//Uint writes uint
func (s *encUints) Uint(v uint) {
	*s = append(*s, v)
}

func (s *encUints) appendUints(vs []uint) {
	*s = append(*s, vs...)
}

func (s *encUints) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecUints
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutUints(data[offset:], *s)
	offset += sizeIntInBytes * size
	return offset, true
}

func (s *encUints) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * sizeIntInBytes)
	}
	return 0
}

//Int64 writes int64
func (s *encInt64s) Int64(v int64) {
	*s = append(*s, v)
}

func (s *encInt64s) appendInt64s(vs []int64) {
	*s = append(*s, vs...)
}

func (s *encInt64s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecInt64s
	offset += size8bitsInBytes
	PutInt32(data[offset:], int32(size))
	offset += size32bitsInBytes
	PutInt64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset, true
}

func (s *encInt64s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size64bitsInBytes)
	}
	return 0
}

//Uint64 write uint64
func (s *encUint64s) Uint64(v uint64) {
	*s = append(*s, v)
}

func (s *encUint64s) appendUint64s(vs []uint64) {
	*s = append(*s, vs...)
}

func (s *encUint64s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecUint64s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutUint64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset, true
}

func (s *encUint64s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size64bitsInBytes)
	}
	return 0
}

//Int32 writes int32
func (s *encInt32s) Int32(v int32) {
	*s = append(*s, v)
}

func (s *encInt32s) appendInt32s(v []int32) {
	*s = append(*s, v...)
}

func (s *encInt32s) store(data []byte, offset int, codec uint8) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codec
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutInt32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset, true
}

func (s *encInt32s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size32bitsInBytes)
	}
	return 0
}

//Uint32 writes uint32
func (s *encUint32s) Uint32(v uint32) {
	*s = append(*s, v)
}

func (s *encUint32s) appendUint32s(v []uint32) {
	*s = append(*s, v...)
}

func (s *encUint32s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecUint32s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutUint32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset, true
}

func (s *encUint32s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size32bitsInBytes)
	}
	return 0
}

//Int16 writes int16
func (s *encInt16s) Int16(v int16) {
	*s = append(*s, v)
}

func (s *encInt16s) appendInt16s(v []int16) {
	*s = append(*s, v...)
}

func (s *encInt16s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecInt16s
	offset += size8bitsInBytes
	PutInt32(data[offset:], int32(size))
	offset += size32bitsInBytes
	PutInt16s(data[offset:], *s)
	offset += size16bitsInBytes * size
	return offset, true
}

func (s *encInt16s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size16bitsInBytes)
	}
	return 0
}

//Uint16 writes uint16
func (s *encUint16s) Uint16(v uint16) {
	*s = append(*s, v)
}

func (s *encUint16s) appendUint16s(v []uint16) {
	*s = append(*s, v...)
}

func (s *encUint16s) store(data []byte, offset int, codec uint8) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codec
	offset += size8bitsInBytes
	PutInt32(data[offset:], int32(size))
	offset += size32bitsInBytes
	PutUint16s(data[offset:], *s)
	offset += size16bitsInBytes * size
	return offset, true
}

func (s *encUint16s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size16bitsInBytes + (size * size64bitsInBytes)
	}
	return 0
}

//Int8 writes int8
func (s *encInt8s) Int8(v int8) {
	*s = append(*s, v)
}

func (s *encInt8s) appendInt8s(v []int8) {
	*s = append(*s, v...)
}

func (s *encInt8s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecInt8s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutInt8s(data[offset:], *s)
	offset += size8bitsInBytes * size
	return offset, true
}

func (s *encInt8s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size8bitsInBytes)
	}
	return 0
}

//Uint8 uint8
func (s *encUint8s) Uint8(v uint8) {
	*s = append(*s, v)
}

func (s *encUint8s) appendUint8s(v []uint8) {
	*s = append(*s, v...)
}

func (s *encUint8s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecUint8s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutUint8s(data[offset:], *s)
	offset += size8bitsInBytes * size
	return offset, true
}

func (s *encUint8s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size8bitsInBytes)
	}
	return 0
}

//Float64 float64
func (s *encFloat64s) Float64(v float64) {
	*s = append(*s, v)
}

func (s *encFloat64s) appendFloat64s(v []float64) {
	*s = append(*s, v...)
}

func (s *encFloat64s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecFloat64s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutFloat64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset, true
}

func (s *encFloat64s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size64bitsInBytes)
	}
	return 0
}

//Float32 writes float32
func (s *encFloat32s) Float32(v float32) {
	*s = append(*s, v)
}

func (s *encFloat32s) appendFloat32s(v []float32) {
	*s = append(*s, v...)
}

func (s *encFloat32s) store(data []byte, offset int) (int, bool) {
	size := len(*s)
	if size == 0 {
		return offset, false
	}
	data[offset] = codecFloat32s
	offset += size8bitsInBytes
	PutUint32(data[offset:], uint32(size))
	offset += size32bitsInBytes
	PutFloat32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset, true
}

func (s *encFloat32s) size() int {
	if size := len(*s); size > 0 {
		return size8bitsInBytes + size32bitsInBytes + (size * size32bitsInBytes)
	}
	return 0
}

//Writers represents writer pool
type Writers struct {
	sync.Pool
}

//Get returns a writer
func (p *Writers) Get() *Writer {
	codec := p.Pool.Get()
	return codec.(*Writer)
}

//NewWriters creates writer pool
func NewWriters() *Writers {
	return &Writers{
		Pool: sync.Pool{
			New: func() interface{} {
				return &Writer{}
			},
		},
	}
}


<|start_filename|>int.go<|end_filename|>
package bintly

import "unsafe"

//PutInt copy int into []byte
func PutInt(dest []byte, v int) {
	copy(dest, (*(*[sizeIntInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Int copy []byte  to int
func Int(b []byte) int {
	v := 0
	copy((*(*[sizeIntInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetUint copy []byte  to uint
func GetUint(b []byte, v *uint) {
	copy((*(*[sizeIntInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutUint copy uint into []byte
func PutUint(dest []byte, v uint) {
	copy(dest, (*(*[sizeIntInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Uint copy []byte  to uint
func Uint(b []byte) uint {
	v := uint(0)
	copy((*(*[sizeIntInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetInt copy []byte  to int
func GetInt(b []byte, v *int) {
	copy((*(*[sizeIntInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutUint64 copy uint64 into []byte
func PutUint64(dest []byte, v uint64) {
	copy(dest, (*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Uint64 copy []byte  to uint64
func Uint64(b []byte) uint64 {
	v := uint64(0)
	copy((*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetUint64 copy []byte  to *uint64
func GetUint64(b []byte, v *uint64) {
	copy((*(*[size64bitsInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutUint32 copy uint32 into []byte
func PutUint32(dest []byte, v uint32) {
	copy(dest, (*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Uint32 copy []byte to uint32
func Uint32(b []byte) uint32 {
	v := uint32(0)
	copy((*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetUint32 copy []byte to *uint32
func GetUint32(b []byte, v *uint32) {
	copy((*(*[size32bitsInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutUint16 copy uint16 into []byte
func PutUint16(dest []byte, v uint16) {
	copy(dest, (*(*[2]byte)(unsafe.Pointer(&v)))[:])
}

//Uint16 copy []byte  to uint16
func Uint16(b []byte) uint16 {
	v := uint16(0)
	copy((*(*[2]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetUint16 copy []byte  to *uint16
func GetUint16(b []byte, v *uint16) {
	copy((*(*[2]byte)(unsafe.Pointer(v)))[:], b)
}

//PutInt64 copy int64 into []byte
func PutInt64(dest []byte, v int64) {
	copy(dest, (*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Int64 copy []byte  to int64
func Int64(b []byte) int64 {
	v := int64(0)
	copy((*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetInt64 copy []byte  to int64
func GetInt64(b []byte, v *int64) {
	copy((*(*[size64bitsInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutInt32 copy int32 into []byte
func PutInt32(dest []byte, v int32) {
	copy(dest, (*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Int32 copy []byte to int32
func Int32(b []byte) int32 {
	v := int32(0)
	copy((*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetInt32 copy []byte to *int32
func GetInt32(b []byte, v *int32) {
	copy((*(*[size32bitsInBytes]byte)(unsafe.Pointer(v)))[:], b)
}

//PutInt16 copy int16 into []byte
func PutInt16(dest []byte, v int16) {
	copy(dest, (*(*[2]byte)(unsafe.Pointer(&v)))[:])
}

//Int16 copy []byte  to int16
func Int16(b []byte) int16 {
	v := int16(0)
	copy((*(*[2]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//GetInt16 copy []byte  to *int16
func GetInt16(b []byte, v *int16) {
	copy((*(*[2]byte)(unsafe.Pointer(v)))[:], b)
}


<|start_filename|>codegen/session.go<|end_filename|>
package codegen

import (
	"github.com/viant/toolbox"
	"os"
	"path"
	"path/filepath"
	"strings"
)

//session stores generated codes, imports, pkg
type session struct {
	*Options
	*toolbox.FileSetInfo
	pkg                 string
	structCodingCode    []string
	generatedTypes      map[string]bool
	imports             map[string]bool
	isBlockTemplateDone bool
}

//shallGenerateCode stores generated codes for all types
func (s *session) shallGenerateCode(typeName string) bool {
	if _, ok := s.generatedTypes[typeName]; ok {
		return false
	}
	s.generatedTypes[typeName] = true
	return true
}

//readPackageCode creates pkg code
func (s *session) readPackageCode() error {
	p, err := filepath.Abs(s.Source)
	if err != nil {
		return err
	}

	var f os.FileInfo
	if f, err = os.Stat(p); err != nil {
		// path/to/whatever does not exist
		return err
	}

	if !f.IsDir() {
		dir, _ := filepath.Split(p)
		_, pkg := path.Split(filepath.Base(dir))
		s.Pkg = pkg
		s.FileSetInfo, err = toolbox.NewFileSetInfo(dir)

	} else {
		_, pkg := path.Split(filepath.Base(p))
		s.Pkg = pkg
		s.FileSetInfo, err = toolbox.NewFileSetInfo(p)
	}

	// if Pkg flag is set use it
	if s.Pkg != "" {
		s.pkg = s.Pkg
	}

	return err
}

//addImports adds imports
func (s *session) addImport(pkg string) {
	s.imports[`"`+pkg+`"`] = true
}

//getImports returns imports
func (s *session) getImports() string {
	return "\t" + strings.Join(toolbox.MapKeysToStringSlice(s.imports), "\n\t")
}

//newSession creates a new session
func newSession(option *Options) *session {
	return &session{Options: option,
		structCodingCode: make([]string, 0),
		generatedTypes:   make(map[string]bool),
		imports:          make(map[string]bool),
	}
}


<|start_filename|>float_test.go<|end_filename|>
package bintly

import (
	"github.com/stretchr/testify/assert"
	"math"
	"math/rand"
	"testing"
)

func TestPutFloat64(t *testing.T) {
	var useCases = []struct {
		description string
		i           float64
	}{
		{
			description: "max float64",
			i:           math.MaxFloat64,
		},
		{
			description: "min float64",
			i:           0,
		},
		{
			description: "random float64",
			i:           rand.Float64(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutFloat64(data, useCase.i)
		actual := Float64(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func TestPutFloat32(t *testing.T) {
	var useCases = []struct {
		description string
		i           float32
	}{
		{
			description: "max float32",
			i:           math.MaxFloat32,
		},
		{
			description: "min float32",
			i:           0,
		},
		{
			description: "random float32",
			i:           rand.Float32(),
		},
	}

	for _, useCase := range useCases {
		var data = make([]byte, 8)
		PutFloat32(data, useCase.i)
		actual := Float32(data)
		assert.EqualValues(t, useCase.i, actual, useCase.description)
	}

}

func BenchmarkPutFloat64(b *testing.B) {
	var bs = make([]byte, 8)
	for i := 0; i < b.N; i++ {
		for _, j := range float64Slice {
			PutFloat64(bs, j)
			a := Float64(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}

func BenchmarkPutFloat32(b *testing.B) {
	var bs = make([]byte, 8)
	for i := 0; i < b.N; i++ {
		for _, j := range float32Slice {
			PutFloat32(bs, j)
			a := Float32(bs)
			if a != j {
				assert.EqualValues(b, j, a)
			}
		}
	}
}


<|start_filename|>coder.go<|end_filename|>
package bintly

import (
	"github.com/viant/bintly/conv"
	"reflect"
	"sync"
)

type structFields struct {
	//indexes of the exported fields
	indexes     []int
	convertible []convField
}

type convField struct {
	index  int
	origin reflect.Type
	native reflect.Type
}

//structCoder represents a struct coder
type structCoder struct {
	mapped map[reflect.Type]*structFields
	ptr    *reflect.Value
	isNil  bool
	v      reflect.Value
	t      reflect.Type
	fields *structFields
}

func (c *structCoder) Alloc() int32 {
	if c.isNil {
		return NilSize
	}
	return 1
}

//SetAlloc set allocation, if zero the pointer to struct is nil
func (c *structCoder) SetAlloc(allocation int32) {
	if allocation <= 0 {
		c.ptr = nil
		return
	}
	if c.v.Kind() == reflect.Ptr {
		v := reflect.New(c.t)
		c.v.Set(v)
		c.v = v.Elem()
	}
}

func (c *structCoder) setFields(t reflect.Type) error {
	if fields, ok := c.mapped[t]; ok {
		c.fields = fields
		return nil
	}
	fields := &structFields{
		indexes:     make([]int, 0),
		convertible: make([]convField, 0),
	}

	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if f.PkgPath != "" {
			continue
		}
		if !conv.IsNative(f.Type) {
			if native := conv.MatchNative(f.Type); native != nil {
				fields.convertible = append(fields.convertible, convField{
					index:  i,
					origin: f.Type,
					native: *native,
				})
				continue
			}
		}
		fields.indexes = append(fields.indexes, i)
	}
	c.mapped[t] = fields
	c.fields = c.mapped[t]
	return nil
}

func (c *structCoder) set(v reflect.Value, t reflect.Type) error {
	c.isNil = false
	c.t = t
	c.v = v
	c.ptr = nil
	if v.Kind() == reflect.Ptr {
		c.ptr = &v
		c.isNil = v.IsNil()
		if !c.isNil {
			c.v = v.Elem()
		}
	}
	return c.setFields(t)
}

//EncodeBinary writes struct to stream
func (c *structCoder) EncodeBinary(stream *Writer) error {
	for _, i := range c.fields.indexes {
		v := c.v.Field(i).Interface()
		if err := stream.Any(v); err != nil {
			return err
		}
	}
	for _, f := range c.fields.convertible {
		v := c.v.Field(f.index).Convert(f.native)
		if err := stream.Any(v.Interface()); err != nil {
			return err
		}
	}
	return nil
}

//DecodeBinary decodes struct from reader
func (c *structCoder) DecodeBinary(stream *Reader) error {
	if c.ptr == nil {
		return nil
	}
	if c.ptr.IsNil() {
		c.v = reflect.New(c.t).Elem()
		c.ptr.Elem().Set(c.v)
	}

	for _, i := range c.fields.indexes {
		v := c.v.Field(i).Addr().Interface()
		if err := stream.Any(v); err != nil {
			return err
		}
	}
	for _, f := range c.fields.convertible {
		v := reflect.New(f.native)
		if err := stream.Any(v.Interface()); err != nil {
			return err
		}
		c.v.Field(f.index).Set(v.Elem().Convert(f.origin))
	}
	return nil
}

type structCoderPool struct {
	sync.Pool
}

func (s *structCoderPool) Get() *structCoder {
	return s.Pool.Get().(*structCoder)
}

func newStructCoderPool() *structCoderPool {
	return &structCoderPool{

		Pool: sync.Pool{
			New: func() interface{} {

				return &structCoder{
					mapped: make(map[reflect.Type]*structFields),
				}
			},
		},
	}
}

var structCoders = newStructCoderPool()

type sliceCoder struct {
	ptr      *reflect.Value
	index    int
	isNil    bool
	v        reflect.Value
	elemType reflect.Type //element type
}

func (c *sliceCoder) set(v reflect.Value, t reflect.Type) {
	c.index = 0
	c.isNil = v.IsNil()
	c.v = v
	if v.Kind() == reflect.Ptr {
		c.ptr = &v
		c.isNil = c.ptr.IsNil()
		if !c.isNil {
			c.v = v.Elem()
		}
	}
	c.elemType = t.Elem()
}

//Alloc returns slice size
func (c *sliceCoder) Alloc() int32 {
	if c.isNil {
		return NilSize
	}
	return int32(c.v.Len())
}

//SetAlloc set allocation, if zero the pointer to struct is nil
func (c *sliceCoder) SetAlloc(allocation int32) {
	if allocation < 0 {
		return
	}
	c.v = reflect.MakeSlice(reflect.SliceOf(c.elemType), int(allocation), int(allocation))
	c.ptr.Elem().Set(c.v)
}

//EncodeBinary writes slice to stream
func (c *sliceCoder) EncodeBinary(stream *Writer) error {
	item := c.v.Index(c.index)
	c.index++
	return stream.Any(item.Interface())
}

//DecodeBinary reads slice from stream
func (c *sliceCoder) DecodeBinary(stream *Reader) error {
	elem := reflect.New(c.elemType)
	if err := stream.Any(elem.Interface()); err != nil {
		return err
	}
	c.v.Index(c.index).Set(elem.Elem())
	c.index++
	return nil
}

type sliceCoderPool struct {
	sync.Pool
}

func (s *sliceCoderPool) Get() *sliceCoder {
	return s.Pool.Get().(*sliceCoder)
}

func newSliceCoderPool() *sliceCoderPool {
	return &sliceCoderPool{
		Pool: sync.Pool{
			New: func() interface{} {
				return &sliceCoder{}
			},
		},
	}
}

var sliceCoders = newSliceCoderPool()

//mapCoder represents a map coder
type mapCoder struct {
	ptr  *reflect.Value
	v    reflect.Value
	t    reflect.Type
	k    reflect.Type
	e    reflect.Type
	iter *reflect.MapIter
}

func (c *mapCoder) set(v reflect.Value, t reflect.Type) {
	c.ptr = nil
	c.v = v
	if v.Kind() == reflect.Ptr {
		c.ptr = &v
	}
	c.t = t
	c.k = t.Key()
	c.e = t.Elem()
}

//Alloc returns slice size
func (c *mapCoder) Alloc() int32 {
	if c.v.IsNil() {
		return NilSize
	}
	c.iter = c.v.MapRange()
	return int32(c.v.Len())
}

//SetAlloc set allocation, if zero the pointer to struct is nil
func (c *mapCoder) SetAlloc(allocation int32) {
	if allocation < 0 {
		return
	}
	c.v = reflect.MakeMapWithSize(c.t, int(allocation))
	c.ptr.Elem().Set(c.v)

}

//EncodeBinary writes slice to stream
func (c *mapCoder) EncodeBinary(stream *Writer) error {
	if !c.iter.Next() {
		return nil
	}
	if err := stream.Any(c.iter.Key().Interface()); err != nil {
		return err
	}
	return stream.Any(c.iter.Value().Interface())
}

//DecodeBinary reads slice from stream
func (c *mapCoder) DecodeBinary(stream *Reader) error {
	key := reflect.New(c.k)
	if err := stream.Any(key.Interface()); err != nil {
		return err
	}
	val := reflect.New(c.e)
	if err := stream.Any(val.Interface()); err != nil {
		return err
	}
	c.v.SetMapIndex(key.Elem(), val.Elem())
	return nil
}

type mapCoderPool struct {
	sync.Pool
}

func (s *mapCoderPool) Get() *mapCoder {
	return s.Pool.Get().(*mapCoder)
}

func newMapCoderPool() *mapCoderPool {
	return &mapCoderPool{
		Pool: sync.Pool{
			New: func() interface{} {
				return &mapCoder{}
			},
		},
	}
}

var mapCoders = newMapCoderPool()


<|start_filename|>floats.go<|end_filename|>
package bintly

import "unsafe"

//PutFloat64s copy []float64 into []byte
func PutFloat64s(bs []byte, vs []float64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetFloat64s copy []byte  into []float64
func GetFloat64s(bs []byte, vs []float64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//PutFloat32s copy []float32 into []byte
func PutFloat32s(bs []byte, vs []float32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetFloat32s copy []byte  into []float32
func GetFloat32s(bs []byte, vs []float32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}


<|start_filename|>example_test.go<|end_filename|>
package bintly_test

import (
	"github.com/viant/bintly"
	"log"
)

//Employee represents a test struct
type Employee struct {
	ID       int
	Name     string
	RolesIDs []int
	Titles   []string
	DeptIDs  []int
}

func Example_Struct_Unmarshal() {
	emp := Employee{
		ID:       100,
		Name:     "test",
		RolesIDs: []int{1000, 1002, 1003},
		Titles:   []string{"Lead", "Principal"},
		DeptIDs:  []int{10, 13},
	}
	data, err := bintly.Marshal(emp)
	if err != nil {
		log.Fatal(err)
	}
	clone := Employee{}
	err = bintly.Unmarshal(data, &clone)
	if err != nil {
		log.Fatal(err)
	}
}

//DecodeBinary decodes data to binary stream
func (e *Employee) DecodeBinary(stream *bintly.Reader) error {
	stream.Int(&e.ID)
	stream.String(&e.Name)
	stream.Ints(&e.RolesIDs)
	stream.Strings(&e.Titles)
	stream.Ints(&e.DeptIDs)
	return nil
}

//EncodeBinary encodes data from binary stream
func (e *Employee) EncodeBinary(stream *bintly.Writer) error {
	stream.Int(e.ID)
	stream.String(e.Name)
	stream.Ints(e.RolesIDs)
	stream.Strings(e.Titles)
	stream.Ints(e.DeptIDs)
	return nil
}

func Example_Slice_Unmarshal() {
	emps := Employees{
		{
			ID:       1,
			Name:     "<NAME>",
			RolesIDs: []int{1000, 1002, 1003},
			Titles:   []string{"Lead", "Principal"},
			DeptIDs:  []int{10, 13},
		},
		{
			ID:       2,
			Name:     "<NAME>",
			RolesIDs: []int{1000, 1002, 1003},
			Titles:   []string{"Lead", "Principal"},
			DeptIDs:  []int{10, 13},
		},
	}

	data, err := bintly.Marshal(&emps) //pass pointer to the slice
	if err != nil {
		log.Fatal(err)
	}
	var clone Employees
	err = bintly.Unmarshal(data, &clone)
	if err != nil {
		log.Fatal(err)
	}
}

func Example_Map_Unmarshal() {
	emps := EmployeesMap{
		1: {
			ID:       1,
			Name:     "<NAME>",
			RolesIDs: []int{1000, 1002, 1003},
			Titles:   []string{"Lead", "Principal"},
			DeptIDs:  []int{10, 13},
		},
		2: {
			ID:       2,
			Name:     "<NAME>",
			RolesIDs: []int{1000, 1002, 1003},
			Titles:   []string{"Lead", "Principal"},
			DeptIDs:  []int{10, 13},
		},
	}

	data, err := bintly.Marshal(&emps) //pass pointer to the map
	if err != nil {
		log.Fatal(err)
	}
	var clone EmployeesMap
	err = bintly.Unmarshal(data, &clone)
	if err != nil {
		log.Fatal(err)
	}
}

//Employees represents Employee slice
type Employees []*Employee

//DecodeBinary decodes data to binary stream
func (e *Employees) DecodeBinary(stream *bintly.Reader) error {
	size := int(stream.Alloc())
	if size == bintly.NilSize {
		return nil
	}
	*e = make([]*Employee, size)
	for i := 0; i < size; i++ {
		if err := stream.Any((*e)[i]); err != nil {
			return err
		}
	}
	return nil
}

//EncodeBinary encodes data from binary stream
func (e *Employees) EncodeBinary(stream *bintly.Writer) error {
	if *e == nil {
		stream.Alloc(bintly.NilSize)
		return nil
	}
	stream.Alloc(int32(len(*e)))
	for i := range *e {
		if err := stream.Any((*e)[i]); err != nil {
			return nil
		}
	}
	return nil
}

//EmployeesMap represents employee maps
type EmployeesMap map[int]Employee

//DecodeBinary decodes data to binary stream
func (e *EmployeesMap) DecodeBinary(stream *bintly.Reader) error {
	size := int(stream.Alloc())
	if size == bintly.NilSize {
		return nil
	}
	*e = make(map[int]Employee, size)
	for i := 0; i < size; i++ {
		var k string
		var v Employee
		if err := stream.Any(&k); err != nil {
			return err
		}
		if err := stream.Any(&v); err != nil {
			return err
		}

	}
	return nil
}

//EncodeBinary encodes data from binary stream
func (e *EmployeesMap) EncodeBinary(stream *bintly.Writer) error {
	if *e == nil {
		stream.Alloc(bintly.NilSize)
		return nil
	}
	stream.Alloc(int32(len(*e)))
	for k, v := range *e {
		if err := stream.Any(k); err != nil {
			return nil
		}
		if err := stream.Any(v); err != nil {
			return nil
		}
	}
	return nil
}


<|start_filename|>codegen/test_data/maps/message.go<|end_filename|>
package maps

type SubMessage struct {
	Id   int
	Name string
}


type M1 map[string][]*SubMessage

type Message struct {
	//M1 map[string]SubMessage
	//M1 map[string]*SubMessage
	//M1 map[string][]SubMessage
	//M1 map[string][]*SubMessage
	 M1
}


<|start_filename|>codegen/helper.go<|end_filename|>
package codegen

import (
	"strings"
)

func firstLetterToUppercase(text string) string {
	return strings.ToUpper(string(text[0:1])) + string(text[1:])
}



<|start_filename|>codegen/types.go<|end_filename|>
package codegen

import "github.com/viant/toolbox"

//isBaseType checks if typeName is primitive types
func isBaseType(typeName string) bool {
	switch typeName {
	case "string", "bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "time.Time",
		"[]string", "[]bool", "[]int", "[]int8", "[]int16", "[]int32", "[]int64", "[]uint", "[]uint8", "[]uint16", "[]uint32", "[]uint64", "[]float32", "[]float64":
		return true
	}
	return false
}

//isStruct return true if type has at least 1 field
func isStruct(aType *toolbox.TypeInfo) bool {
	return len(aType.Fields()) > 0
}


<|start_filename|>codec_test.go<|end_filename|>
package bintly

import (
	"github.com/stretchr/testify/assert"
	"math"
	"reflect"
	"testing"
	"time"
)

func TestCodec_Put(t *testing.T) {
	type myInt int
	mI := myInt(333)
	var tBool = true
	var text = "testMe"
	var ts = time.Now()
	var useCases = []struct {
		description string
		value       interface{}
	}{
		{
			description: "int type",
			value:       (1024 * 1024 * 512),
		},
		{
			description: "int ptr type",
			value:       &intSlice[0],
		},
		{
			description: "[]int type",
			value:       intSlice,
		},

		{
			description: "uint type",
			value:       uint(1024 * 1024 * 512),
		},
		{
			description: "uint ptr type",
			value:       &uintSlice[0],
		},
		{
			description: "[]uint  type",
			value:       uintSlice,
		},
		{
			description: "int64 type",
			value:       int64(1024 * 1024 * 512),
		},
		{
			description: "int64 ptr type",
			value:       &int64Slice[0],
		},
		{
			description: "[]int64  type",
			value:       int64Slice,
		},
		{
			description: "uint64 type",
			value:       uint64(1024 * 1024 * 512),
		},
		{
			description: "int64 ptr type",
			value:       &uint64slice[0],
		},
		{
			description: "[]int64  type",
			value:       uint64slice,
		},
		{
			description: "int32 type",
			value:       int32(1024 * 1024 * 512),
		},
		{
			description: "*int32 type",
			value:       &int32Slice[0],
		},
		{
			description: "[]int32 type",
			value:       int32Slice,
		},
		{
			description: "uint32 type",
			value:       uint32(1024 * 1024 * 512),
		},
		{
			description: "*uint32 type",
			value:       &uint32Slice[0],
		},
		{
			description: "[]uint32 type",
			value:       uint32Slice,
		},

		{
			description: "uint16 type",
			value:       uint16(math.MaxInt16) - 100,
		},
		{
			description: "*uint16 type",
			value:       &uint16Slice[0],
		},
		{
			description: "[]uint16 type",
			value:       uint16Slice,
		},
		{
			description: "int16 type",
			value:       int16(math.MaxInt16) - 100,
		},
		{
			description: "*int16 type",
			value:       &int16Slice[0],
		},
		{
			description: "[]int16 type",
			value:       int16Slice,
		},
		{
			description: "uint8 type",
			value:       uint8(math.MaxInt8) - 100,
		},
		{
			description: "*uint8 type",
			value:       &uint8Slice[0],
		},
		{
			description: "[]uint8 type",
			value:       uint8Slice,
		},
		{
			description: "int8 type",
			value:       int8(math.MaxInt8) - 100,
		},
		{
			description: "*int8 type",
			value:       &int8Slice[0],
		},
		{
			description: "[]int8 type",
			value:       int8Slice,
		},

		{
			description: "float64 type",
			value:       float64(3.123),
		},
		{
			description: "*float64 type",
			value:       &float64Slice[0],
		},
		{
			description: "[]float64 type",
			value:       float64Slice,
		},
		{
			description: "float32 type",
			value:       float32(3.333333),
		},
		{
			description: "*float32 type",
			value:       &float32Slice[0],
		},
		{
			description: "[]float32 type",
			value:       float32Slice,
		},
		{
			description: "bool type",
			value:       true,
		},
		{
			description: "*bool type",
			value:       &tBool,
		},
		{
			description: "[]bool type",
			value:       []bool{true, false, true},
		},
		{
			description: "[]byte type",
			value:       []byte(uint8Slice),
		},
		{
			description: "string type",
			value:       "abc",
		},
		{
			description: "*string type",
			value:       &text,
		},

		{
			description: "[]string type",
			value:       stringSlice,
		},
		{
			description: "time.Time",
			value:       ts,
		},
		{
			description: "*time.Time",
			value:       &ts,
		},
		{
			description: "myInt native type",
			value:       myInt(101),
		},
		{
			description: "*myInt native type",
			value:       &mI,
		},
	}

	for _, useCase := range useCases {
		encoder := &Writer{}

		err := encoder.Any(useCase.value)
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		data := encoder.Bytes()
		decoder := &Reader{}
		decoder.FromBytes(data)
		actualPtr := reflect.New(reflect.TypeOf(useCase.value))
		err = decoder.Any(actualPtr.Interface())
		if !assert.Nil(t, err, useCase.description) {
			continue
		}
		actual := actualPtr.Elem().Interface()
		expect := useCase.value
		if actualPtr.Elem().Kind() == reflect.Ptr {
			actual = actualPtr.Elem().Elem().Interface()
			expect = reflect.ValueOf(expect).Elem().Interface()
		}
		if actualTime, ok := actual.(time.Time); ok {
			expectedTime := expect.(time.Time)
			actual = actualTime.UnixNano()
			expect = expectedTime.UnixNano()
		} else if actualTime, ok := actual.(*time.Time); ok {
			expectedTime := expect.(*time.Time)
			actual = actualTime.UnixNano()
			expect = expectedTime.UnixNano()
		}
		assert.EqualValues(t, expect, actual, useCase.description)
	}



}


<|start_filename|>conv/native.go<|end_filename|>
package conv

import "reflect"

var intType = reflect.TypeOf(0)
var uintType = reflect.TypeOf(uint(0))
var int64Type = reflect.TypeOf(int64(0))
var uint64Type = reflect.TypeOf(uint64(0))
var int32Type = reflect.TypeOf(int32(0))
var uint32Type = reflect.TypeOf(uint32(0))
var int16Type = reflect.TypeOf(int16(0))
var uint16Type = reflect.TypeOf(uint16(0))
var int8Type = reflect.TypeOf(int8(0))
var uint8Type = reflect.TypeOf(uint8(0))
var float64Type = reflect.TypeOf(float64(0))
var float32Type = reflect.TypeOf(float32(0))
var boolType = reflect.TypeOf(true)
var stringType = reflect.TypeOf("")
var bytesType = reflect.TypeOf([]byte{})

func IsNative(t reflect.Type) bool {
	switch t {
	case intType, uintType, int64Type, uint64Type, int32Type, uint32Type,
		int16Type, uint16Type, int8Type, uint8Type,
		float64Type, float32Type, boolType, stringType, bytesType:
		return true
	}
	return false
}

//MatchNative returns matched alias native type pointer or nil
func MatchNative(t reflect.Type) *reflect.Type {
	switch t.Kind() {
	case reflect.Int:
		return &intType
	case reflect.Uint:
		return &uintType
	case reflect.Int64:
		return &int64Type
	case reflect.Uint64:
		return &uint64Type
	case reflect.Int32:
		return &int32Type
	case reflect.Uint32:
		return &uint32Type
	case reflect.Int16:
		return &int16Type
	case reflect.Uint16:
		return &uint16Type
	case reflect.Int8:
		return &int8Type
	case reflect.Uint8:
		return &uint8Type
	case reflect.Float64:
		return &float64Type
	case reflect.Float32:
		return &float32Type
	case reflect.Bool:
		return &boolType
	case reflect.String:
		return &stringType
	}
	if IsBytesConvertibleTo(t) {
		return &bytesType
	}
	return nil
}

//IsByteConvertibleTo return true if []byte ConvertibleTo
func IsBytesConvertibleTo(t reflect.Type) bool {
	return t.ConvertibleTo(bytesType)
}


<|start_filename|>decoder.go<|end_filename|>
package bintly

//Decoder represents a decoder interface
type Decoder interface {
	DecodeBinary(stream *Reader) error
}

//Allocator represents repeated type allocator
type Allocator interface {
	SetAlloc(allocation int32)
}


<|start_filename|>codegen/template.go<|end_filename|>
package codegen

import (
	"bytes"
	"fmt"
	"text/template"
)

const (
	decodeBaseType = iota
	encodeBaseType
	decodeDerivedBaseType
	encodeDerivedBaseType
	decodeBaseSliceType
	encodeBaseSliceType
	decodeCustomSliceType
	encodeCustomSliceType
	encodeStructType
	decodeStructType
	encodeSliceStructType
	decodeSliceStructType
	encodeEmbeddedAliasTemplate
	decodeEmbeddedAliasSliceTemplate
	encodeBasicMapTemplate
	decodeBasicMapTemplate
	encodeSliceMapTemplate
	decodeSliceMapTemplate
)

var fieldTemplate = map[int]string{
	encodeBaseType: `	coder.{{.Method}}({{.ReceiverAlias}}.{{.Field}})`,
	decodeBaseType: `	coder.{{.Method}}(&{{.ReceiverAlias}}.{{.Field}})`,
	decodeDerivedBaseType: `	var {{.TransientVar}} {{.BaseType}}
	coder.{{.Method}}(&{{.TransientVar}})
	{{.ReceiverAlias}}.{{.Field}} = {{.FieldType}}({{.TransientVar}})`,
	encodeDerivedBaseType: `	coder.{{.Method}}({{.BaseType}}({{.ReceiverAlias}}.{{.Field}}))`,
	encodeBaseSliceType: `	coder.{{.Method}}(({{.ReceiverAlias}}.{{.Field}}))`,
	decodeBaseSliceType: `	var {{.TransientVar}} []{{.BaseType}}
	coder.{{.Method}}(&{{.TransientVar}})
	{{.ReceiverAlias}}.{{.Field}} = {{.TransientVar}}`,
	encodeCustomSliceType: `	coder.{{.Method}}(*(*[]{{.BaseType}})(unsafe.Pointer(&{{.ReceiverAlias}}.{{.Field}})))`,
	decodeCustomSliceType: `	var {{.TransientVar}} []{{.BaseType}}
	coder.{{.Method}}(&{{.TransientVar}})
	{{.ReceiverAlias}}.{{.Field}} = *(*{{.FieldType}})(unsafe.Pointer(&{{.TransientVar}}))`,
	encodeStructType: `	coder.{{.Method}}({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}})`,
	decodeStructType: `{{if not .PointerNeeded}}	{{.ReceiverAlias}}.{{.Field}} = &{{.FieldType}}{}
{{end}}	coder.{{.Method}}({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}})`,
	encodeSliceStructType: `	var {{.TransientVar}} = len({{.ReceiverAlias}}.{{.Field}})
	coder.Alloc(int32({{.TransientVar}}))
	for i:=0; i < {{.TransientVar}} ; i++ {
		if err := coder.{{.Method}}({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}}[i]);err !=nil {
			return nil
		}
	}`,
	decodeSliceStructType: `	var {{.TransientVar}} = coder.Alloc()
	{{.ReceiverAlias}}.{{.Field}} = make([]{{if not .PointerNeeded}}*{{end}}{{.FieldType}},{{.TransientVar}})
	for i:=0; i < int({{.TransientVar}}) ; i++ {
		if err := coder.{{.Method}}({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}}[i]);err != nil {
			return nil
		}
	}`,
	encodeEmbeddedAliasTemplate: `	{{if not .PointerNeeded}}{{.ReceiverAlias}}.{{.Field}} = &{{.FieldType}}{}{{end}}
	if err := coder.Coder({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}}); err !=nil {
	return err
	}`,
	decodeEmbeddedAliasSliceTemplate: `		if err := coder.Coder({{if .PointerNeeded}}&{{end}}{{.ReceiverAlias}}.{{.Field}}); err != nil {
		return err
	}`,
	encodeBasicMapTemplate: `	coder.Alloc(int32(len({{.ReceiverAlias}}.{{.Field}})))
	for k, v := range {{.ReceiverAlias}}.{{.Field}} {
		coder.{{.KeyMethod}}(k)
		coder.{{.ValueMethod}}({{if .PointerNeeded}}&{{end}}v)
	}`,
	decodeBasicMapTemplate: `	 {
		size := int(coder.Alloc())
		if size == bintly.NilSize {
			return nil
		}
		{{.ReceiverAlias}}.{{.Field}} = make(map[{{.KeyFieldType}}]{{.ValueFieldType}},size)
		for i:=0 ; i < size ; i++ {
			var k {{.KeyFieldType}}
			var v ={{if .PointerMethod}}&{{end}}{{.BaseValueFieldType}}{}
			coder.{{.KeyMethod}}(&k)
			coder.{{.ValueMethod}}({{if .PointerNeeded}}&{{end}}v)
			{{.ReceiverAlias}}.{{.Field}}[k]=v
		}
	}`,
	encodeSliceMapTemplate: ` {	
	coder.Alloc(int32(len({{.ReceiverAlias}}.{{.Field}})))
	for k, v := range {{.ReceiverAlias}}.{{.Field}} {
		coder.{{.KeyMethod}}(k)
		var m1 = len(v)
		coder.Alloc(int32(m1))
		for i:=0; i< m1;i++ {
			if err := coder.{{.ValueMethod}}({{if .PointerNeeded}}&{{end}}v[i]);err != nil {
				return nil
			}
		}
	}
	}`,
	decodeSliceMapTemplate: `	 {
		size := int(coder.Alloc())
		if size == bintly.NilSize {
			return nil
		}
		{{.ReceiverAlias}}.{{.Field}} = make(map[{{.KeyFieldType}}]{{.ValueFieldType}},size)
		for i:=0 ; i < size ; i++ {
			var k {{.KeyFieldType}}
			var v {{.ValueFieldType}}
			coder.{{.KeyMethod}}(&k)
			var m1Size = coder.Alloc()
			v = make({{.ValueFieldType}},m1Size)
			for j:=0; j < int(m1Size); j++ {	
				{{if .PointerMethod}}v[j]=&{{.BaseValueFieldType}}{}{{end}}
				if err := coder.{{.ValueMethod}}({{if .PointerNeeded}}&{{end}}v[j]);err !=nil {	
				 	return nil
				}
			}
			{{.ReceiverAlias}}.{{.Field}}[k]=v
		}
	}`,
}


const (
	fileCode = iota
	codingStructType
	codingSliceType
)

var blockTemplate = map[int]string{
	fileCode: `// Code generated by bintly codegen. DO NOT EDIT.\n\n

package {{.Pkg}}

import (
{{.Imports}}
)
{{.Code}}

`,
	codingStructType: `
func ({{.Receiver}}) EncodeBinary(coder *bintly.Writer) error {
{{.EncodingCases}}
	return nil
}
func ({{.Receiver}}) DecodeBinary(coder *bintly.Reader) error {
{{.DecodingCases}}	
	return nil
}
`,
	codingSliceType: `func ({{.ReceiverAlias}} *{{.SliceType}}) EncodeBinary(coder *bintly.Writer) error {
	var size = len(*{{.ReceiverAlias}})
	coder.Alloc(int32(size))
	for i:=0; i < size ; i++ {
		if err := coder.Coder({{if not .IsPointer}}&{{end}}(*{{.ReceiverAlias}})[i]);err !=nil {
			return nil
		}
	}
	return nil
}

func ({{.ReceiverAlias}} *{{.SliceType}}) DecodeBinary(coder *bintly.Reader) error  {
	var tmp = coder.Alloc()
	*{{.ReceiverAlias}} = make([]{{if .IsPointer}}*{{end}}{{.ComponentType}},tmp)
	for i:=0; i < int(tmp) ; i++ {
		tmp := 	{{if .IsPointer}}&{{end}}{{.ComponentType}}{}
		if err := coder.Coder({{if not .IsPointer}}&{{end}}(*{{.ReceiverAlias}})[i]);err != nil {
			return nil
		}
		(*{{.ReceiverAlias}})[i] = tmp
	}
	return nil
}
`,
}

//expandTemplate replaces templates parameters with actual data
func expandTemplate(namespace string, dictionary map[int]string, key int, data interface{}) (string, error) {
	var id = fmt.Sprintf("%v_%v", namespace, key)
	textTemplate, ok := dictionary[key]
	if !ok {
		return "", fmt.Errorf("failed to lookup template for %v.%v", namespace, key)
	}
	temlate, err := template.New(id).Parse(textTemplate)
	if err != nil {
		return "", fmt.Errorf("fiailed to parse template %v %v, due to %v", namespace, key, err)
	}
	writer := new(bytes.Buffer)
	err = temlate.Execute(writer, data)
	return writer.String(), err
}

//expandFieldTemplate replaces template fields with data
func expandFieldTemplate(key int, data interface{}) (string, error) {
	return expandTemplate("fieldTemplate", fieldTemplate, key, data)
}

//expandBlockTemplate replaces template block with data
func expandBlockTemplate(key int, data interface{}) (string, error) {
	return expandTemplate("blockTemplate", blockTemplate, key, data)
}


<|start_filename|>conv/native_test.go<|end_filename|>
package conv

import (
	"github.com/stretchr/testify/assert"
	"reflect"
	"testing"
)

func TestIsNative(t *testing.T) {
	type intAlias int
	type uintAlias uint
	type int64Alias int64
	type uint64Alias uint64
	type int32Alias int32
	type uint32Alias uint32
	type int16Alias int16
	type uint16Alias uint16
	type int8Alias int8
	type uint8Alias uint8
	type float64Alias float64
	type float32Alias float32
	type boolAlias bool
	type stringAlias string
	type btesType []byte

	var useCases = []struct {
		description string
		value       interface{}
		nativeType  *reflect.Type
	}{
		{
			description: "int alias",
			value:       intAlias(0),
			nativeType:  &intType,
		},
		{
			description: "uint alias",
			value:       uintAlias(0),
			nativeType:  &uintType,
		},
		{
			description: "int64 alias",
			value:       int64Alias(0),
			nativeType:  &int64Type,
		},
		{
			description: "uint64 alias",
			value:       uint64Alias(0),
			nativeType:  &uint64Type,
		},
		{
			description: "int32 alias",
			value:       int32Alias(0),
			nativeType:  &int32Type,
		},
		{
			description: "uint32 alias",
			value:       uint32Alias(0),
			nativeType:  &uint32Type,
		},
		{
			description: "int16 alias",
			value:       int16Alias(0),
			nativeType:  &int16Type,
		},
		{
			description: "uint16 alias",
			value:       uint16Alias(0),
			nativeType:  &uint16Type,
		},
		{
			description: "int8 alias",
			value:       int8Alias(0),
			nativeType:  &int8Type,
		},
		{
			description: "uint8 alias",
			value:       uint8Alias(0),
			nativeType:  &uint8Type,
		},
		{
			description: "bool alias",
			value:       boolAlias(true),
			nativeType:  &boolType,
		},
		{
			description: "float64 alias",
			value:       float64Alias(0.1),
			nativeType:  &float64Type,
		},
		{
			description: "float32 alias",
			value:       float32Alias(0.1),
			nativeType:  &float32Type,
		},
		{
			description: "string alias",
			value:       stringAlias("a"),
			nativeType:  &stringType,
		},
		{
			description: "[]byte alias",
			value:       btesType("a"),
			nativeType:  &bytesType,
		},
	}

	for _, useCase := range useCases {
		assert.False(t, IsNative(reflect.TypeOf(useCase.value)), useCase.description)
		assert.True(t, IsNative(*useCase.nativeType), useCase.description)

		actual := *MatchNative(reflect.TypeOf(useCase.value))
		expect := *useCase.nativeType
		assert.EqualValues(t, expect.Name(), actual.Name(), useCase.description)
	}

}


<|start_filename|>float.go<|end_filename|>
package bintly

import "unsafe"

//PutFloat64 copy float64 into []byte
func PutFloat64(dest []byte, v float64) {
	copy(dest, (*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Float64 copy []byte  to float64
func Float64(b []byte) float64 {
	v := float64(0)
	copy((*(*[size64bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}

//PutFloat32 copy float32 into []byte
func PutFloat32(dest []byte, v float32) {
	copy(dest, (*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:])
}

//Float32 copy []byte to float32
func Float32(b []byte) float32 {
	v := float32(0)
	copy((*(*[size32bitsInBytes]byte)(unsafe.Pointer(&v)))[:], b)
	return v
}


<|start_filename|>ints.go<|end_filename|>
package bintly

import (
	"unsafe"
)

const (
	n = 2048
)

//PutInts copy []int into []byte
func PutInts(bs []byte, vs []int) {
	bsLen := len(vs) * sizeIntInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / sizeIntInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / sizeIntInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//Ints copy []byte  into []int
func Ints(bs []byte) []int {
	vs := make([]int, len(bs)/sizeIntInBytes)
	GetInts(bs, vs)
	return vs
}

//GetInts copy []byte  into []int
func GetInts(bs []byte, vs []int) {
	bsLen := len(vs) * sizeIntInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / sizeIntInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / sizeIntInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//PutUints copy []uint into []byte
func PutUints(bs []byte, vs []uint) {
	bsLen := len(vs) * sizeIntInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / sizeIntInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / sizeIntInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetUints copy []byte  into []uint
func GetUints(bs []byte, vs []uint) {
	bsLen := len(vs) * sizeIntInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / sizeIntInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / sizeIntInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//PutUint64s copy []uint64 into []byte
func PutUint64s(bs []byte, vs []uint64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetUint64s copy []byte  into []uint64
func GetUint64s(bs []byte, vs []uint64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Uint64s copy []byte  into []uint64
func Uint64s(bs []byte) []uint64 {
	vs := make([]uint64, len(bs)/size64bitsInBytes)
	GetUint64s(bs, vs)
	return vs
}

//PutUint32s copy []uint32 into []byte
func PutUint32s(bs []byte, vs []uint32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetUint32s copy []byte  into []uint32
func GetUint32s(bs []byte, vs []uint32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Uint32s copy []byte  into []uint32
func Uint32s(bs []byte) []uint32 {
	vs := make([]uint32, len(bs)/size32bitsInBytes)
	GetUint32s(bs, vs)
	return vs
}

//PutUint16s copy []uint16 into []byte
func PutUint16s(bs []byte, vs []uint16) {
	bsLen := len(vs) * size16bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size16bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size16bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetUint16s copy []byte  into []uint16
func GetUint16s(bs []byte, vs []uint16) {
	bsLen := len(vs) * size16bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size16bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size16bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Uint16s copy []byte  into []uint16
func Uint16s(bs []byte) []uint16 {
	vs := make([]uint16, len(bs)/size16bitsInBytes)
	GetUint16s(bs, vs)
	return vs
}

//PutInt64s copy []int64 into []byte
func PutInt64s(bs []byte, vs []int64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetInt64s copy []byte  into []int64
func GetInt64s(bs []byte, vs []int64) {
	bsLen := len(vs) * size64bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size64bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size64bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Int64s copy []byte  into []int64
func Int64s(bs []byte) []int64 {
	vs := make([]int64, len(bs)/size64bitsInBytes)
	GetInt64s(bs, vs)
	return vs
}

//PutInt32s copy []int32 into []byte
func PutInt32s(bs []byte, vs []int32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetInt32s copy []byte  into []int32
func GetInt32s(bs []byte, vs []int32) {
	bsLen := len(vs) * size32bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size32bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size32bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Int32s copy []byte  into []int32
func Int32s(bs []byte) []int32 {
	vs := make([]int32, len(bs)/size32bitsInBytes)
	GetInt32s(bs, vs)
	return vs
}

//PutInt16s copy []int16 into []byte
func PutInt16s(bs []byte, vs []int16) {
	bsLen := len(vs) * size16bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size16bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size16bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetInt16s copy []byte  into []int16
func GetInt16s(bs []byte, vs []int16) {
	bsLen := len(vs) * size16bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size16bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size16bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Int16s copy []byte  into []int16
func Int16s(bs []byte) []int16 {
	vs := make([]int16, len(bs)/size16bitsInBytes)
	GetInt16s(bs, vs)
	return vs
}

//PutInt8s copy []int8 into []byte
func PutInt8s(bs []byte, vs []int8) {
	bsLen := len(vs) * size8bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size8bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size8bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetInt8s copy []byte  into []int8
func GetInt8s(bs []byte, vs []int8) {
	bsLen := len(vs) * size8bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size8bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size8bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Int8s copy []byte  into []int8
func Int8s(bs []byte) []int8 {
	vs := make([]int8, len(bs)/size8bitsInBytes)
	GetInt8s(bs, vs)
	return vs
}

//PutUint8s copy []uint8 into []byte
func PutUint8s(bs []byte, vs []uint8) {
	bsLen := len(vs) * size8bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size8bitsInBytes
		copy(bs[bsOffset:bsOffset+n], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size8bitsInBytes
	copy(bs[bsOffset:bsOffset+vsLimit], (*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit])
}

//GetUint8s copy []byte  into []uint8
func GetUint8s(bs []byte, vs []uint8) {
	bsLen := len(vs) * size8bitsInBytes
	chunks := bsLen / n
	bsOffset := 0
	for i := 0; i < chunks; i++ {
		index := bsOffset / size8bitsInBytes
		copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:n], bs[bsOffset:bsOffset+n])
		bsOffset += n
	}
	vsLimit := bsLen % n
	if vsLimit == 0 {
		return
	}
	index := bsOffset / size8bitsInBytes
	copy((*(*[n]byte)(unsafe.Pointer(&vs[index])))[:vsLimit], bs[bsOffset:bsOffset+vsLimit])
}

//Uint8s copy []byte  into []uint8
func Uint8s(bs []byte) []uint8 {
	vs := make([]uint8, len(bs)/size8bitsInBytes)
	GetUint8s(bs, vs)
	return vs
}


<|start_filename|>codegen/options.go<|end_filename|>
package codegen

import (
	"errors"
	"strings"
)

//Options represents Cli options
type Options struct {
	Source string   `short:"s" long:"sourceURL" description:"source URL"`
	Dest   string   `short:"d" long:"destinationURL" description:"destination URL"`
	Types  []string `short:"t" long:"struct type" description:"struct type"`
	Pkg    string   `short:"p" long:"package" description:"package"`
}

//Validate validates input options
func (o *Options) Validate() error {
	if o == nil {
		return errors.New("options is nil")
	}
	if o.Source == "" {
		return errors.New("source is empty")
	}
	if o.Types == nil || len(o.Types) == 0 {
		return errors.New("type is empty")
	}
	var srcPrefix = o.Dest
	if o.Dest == "" {
		srcPrefix = o.Source[:strings.LastIndex(o.Source, "/")]
	}
	o.Dest = srcPrefix + strings.Split(o.Source[strings.LastIndex(o.Source, "/"):], ".")[0] + "_enc.go"
	return nil
}


<|start_filename|>codegen/test_data/primitive_alias/message.go<|end_filename|>
package primitive_alias

import "time"

type Aint int
type SliceInt []int
type Aints []Aint
type Astring string
type Astrings []Astring

type Tt struct {
	Id   int
	Name string
}

type Message struct {
	T2 Tt
	C1 SliceInt
	A1 Aint
	D1 Aints
	S1 Astrings
	T1 time.Time
}


<|start_filename|>stress/bench.go<|end_filename|>
package stress

import (
	"encoding/binary"
	"github.com/viant/bintly"
	bin "github.com/viant/bintly/binary"
)

type (
	//BenchStruct represents a bench struct
	BenchStruct struct {
		A1 int
		A2 string
		A3 bool
		A4 float64
		A5 []int
		A6 []string
		A7 []float64
		A8 []byte
	}
	//BenchStructAlias alias to benchmark reflection
	BenchStructAlias BenchStruct
)

//DecodeBinary decode bindly stream
func (m *BenchStruct) DecodeBinary(stream *bintly.Reader) error {
	stream.Int(&m.A1)
	stream.String(&m.A2)
	stream.Bool(&m.A3)
	stream.Float64(&m.A4)
	stream.Ints(&m.A5)
	stream.Strings(&m.A6)
	stream.Float64s(&m.A7)
	stream.Uint8s(&m.A8)
	return nil
}

//EncodeBinary encodes bintly stream
func (m *BenchStruct) EncodeBinary(stream *bintly.Writer) error {
	stream.Int(m.A1)
	stream.String(m.A2)
	stream.Bool(m.A3)
	stream.Float64(m.A4)
	stream.Ints(m.A5)
	stream.Strings(m.A6)
	stream.Float64s(m.A7)
	stream.Uint8s(m.A8)
	return nil
}

//ToBytes converts to bytes with wrapped encoding/binary ByteOrder
func (m *BenchStruct) ToBytes() ([]byte, error) {
	writer := bin.NewWriter(binary.LittleEndian)
	if err := writer.Int(m.A1); err != nil {
		return nil, err
	}
	if err := writer.String(m.A2); err != nil {
		return nil, err
	}
	if err := writer.Bool(m.A3); err != nil {
		return nil, err
	}
	if err := writer.Float64(m.A4); err != nil {
		return nil, err
	}
	if err := writer.Ints(m.A5); err != nil {
		return nil, err
	}
	if err := writer.Strings(m.A6); err != nil {
		return nil, err
	}
	if err := writer.Float64s(m.A7); err != nil {
		return nil, err
	}
	if err := writer.Bytes(m.A8); err != nil {
		return nil, err
	}
	return writer.ToBytes(), nil
}

//ToBytes converts from bytes with wrapped encoding/binary ByteOrder
func (m *BenchStruct) FromBytes(bs []byte) {
	reader := bin.NewReader(bs, binary.LittleEndian)
	m.A1 = reader.Int()
	m.A2 = reader.String()
	m.A3 = reader.Bool()
	m.A4 = reader.Float64()
	m.A5 = reader.Ints()
	m.A6 = reader.Strings()
	m.A7 = reader.Float64s()
	m.A8 = reader.Bytes()
}


<|start_filename|>codegen/generator_test.go<|end_filename|>
package codegen

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/toolbox"
	"os"
	"path"
	"testing"
)

func TestGen(t *testing.T) {

	parent := path.Join(toolbox.CallerDirectory(3), "test_data")
	os.Setenv("AST_DEBUG","0")
	var useCases = []struct {
		description string
		options     *Options
		hasError    bool
	}{

		{
			description: "map  types",
			options: &Options{
				Source: path.Join(parent, "maps"),
				Types:  []string{"Message"},
				Dest:   path.Join(parent, "maps", "message_enc.go"),
			},
		},
		{
			description: "slice  types",
			options: &Options{
				Source: path.Join(parent, "slices"),
				Types:  []string{"Message"},
				Dest:   path.Join(parent, "slices", "message_enc.go"),
			},
		},
		{
			description: "message  types",
			options: &Options{
				Source: path.Join(parent, "messages"),
				Types:  []string{"Message"},
				Dest:   path.Join(parent, "messages", "message_enc.go"),
			},
		},
		{
			description: "basic struct code generation",
			options: &Options{
				Source: path.Join(parent, "basic_struct"),
				Types:  []string{"Message"},
				Dest:   path.Join(parent, "basic_struct", "basic_struct.go"),
			},
		},
		{
			description: "basic aliased types",
			options: &Options{
				Source: path.Join(parent, "primitive_alias"),
				Types:  []string{"Message"},
				Dest:   path.Join(parent, "primitive_alias", "primitive_alias.go"),
			},
		},
	}

	for _, useCase := range useCases[0:1] {
		err := Generate(useCase.options)
		assert.Nil(t, err, useCase.hasError)

	}
}


<|start_filename|>reader.go<|end_filename|>
package bintly

import (
	"fmt"
	"github.com/viant/bintly/conv"
	"reflect"
	"sync"
	"time"
)

type (
	//Reader represents binary readers
	Reader struct {
		decAlloc decInt32s
		decMAlloc decUint16s
		decInts
		decUints
		decInt64s
		decUint64s
		decInt32s
		decUint32s
		decInt16s
		decUint16s
		decInt8s
		decUint8s
		decFloat64s
		decFloat32s
	}

	decInts     []int
	decUints    []uint
	decInt64s   []int64
	decUint64s  []uint64
	decInt32s   []int32
	decUint32s  []uint32
	decInt16s   []int16
	decUint16s  []uint16
	decInt8s    []int8
	decUint8s   []uint8
	decFloat64s []float64
	decFloat32s []float32
)

//Any returns value into source pointer, source has to be a pointer
func (r *Reader) Any(v interface{}) error {
	switch actual := v.(type) {
	case *int:
		r.Int(actual)
	case **int:
		r.IntPtr(actual)
	case *[]int:
		r.Ints(actual)
	case *uint:
		r.Uint(actual)
	case **uint:
		r.UintPtr(actual)
	case *[]uint:
		r.Uints(actual)
	case *int64:
		r.Int64(actual)
	case **int64:
		r.Int64Ptr(actual)
	case *[]int64:
		r.Int64s(actual)
	case *uint64:
		r.Uint64(actual)
	case **uint64:
		r.Uint64Ptr(actual)
	case *[]uint64:
		r.Uint64s(actual)
	case *int32:
		r.Int32(actual)
	case **int32:
		r.Int32Ptr(actual)
	case *[]int32:
		r.Int32s(actual)
	case *uint32:
		r.Uint32(actual)
	case **uint32:
		r.Uint32Ptr(actual)
	case *[]uint32:
		r.Uint32s(actual)
	case *uint16:
		r.Uint16(actual)
	case **uint16:
		r.Uint16Ptr(actual)
	case *[]uint16:
		r.Uint16s(actual)
	case *int16:
		r.Int16(actual)
	case **int16:
		r.Int16Ptr(actual)
	case *[]int16:
		r.Int16s(actual)
	case *uint8:
		r.Uint8(actual)
	case **uint8:
		r.Uint8Ptr(actual)
	case *[]uint8:
		r.Uint8s(actual)
	case *int8:
		r.Int8(actual)
	case **int8:
		r.Int8Ptr(actual)
	case *[]int8:
		r.Int8s(actual)
	case *float64:
		r.Float64(actual)
	case **float64:
		r.Float64Ptr(actual)
	case *[]float64:
		r.Float64s(actual)
	case *float32:
		r.Float32(actual)
	case **float32:
		r.Float32Ptr(actual)
	case *[]float32:
		r.Float32s(actual)
	case *bool:
		r.Bool(actual)
	case **bool:
		r.BoolPtr(actual)
	case *[]bool:
		r.Bools(actual)
	case *string:
		r.String(actual)
	case **string:
		r.StringPtr(actual)
	case *[]string:
		r.Strings(actual)
	case *time.Time:
		r.Time(actual)
	case **time.Time:
		r.TimePtr(actual)
	default:
		coder, ok := v.(Decoder)
		if ok {
			return r.Coder(coder)
		}
		return r.anyReflect(v)
	}
	return nil
}

//Alloc shifts allocation size (for repeated or pointers(nil:0,1))
func (r *Reader) Alloc() int32 {
	alloc := r.decAlloc[0]
	r.decAlloc = r.decAlloc[1:]
	return alloc
}

//MAlloc shifts allocation size (for repeated or pointers(nil:0,1))
func (r *Reader) MAlloc() uint16 {
	alloc := r.decMAlloc[0]
	r.decMAlloc = r.decMAlloc[1:]
	return alloc
}

//Int reads into *int
func (r *Reader) Int(v *int) {
	*v = r.decInts[0]
	r.decInts = r.decInts[1:]
}

//IntPtr reads into **int
func (r *Reader) IntPtr(v **int) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decInts[0]
	r.decInts = r.decInts[1:]
	*v = &i
}

//Ints reads into *[]int
func (r *Reader) Ints(vs *[]int) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decInts[:size]
	*vs = s
	r.decInts = r.decInts[size:]
}


//MInts reads medium size slice into *[]int
func (r *Reader) MInts(vs *[]int) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decInts[:size]
	*vs = s
	r.decInts = r.decInts[size:]
}

//Uint reads into *uint
func (r *Reader) Uint(v *uint) {
	*v = r.decUints[0]
	r.decUints = r.decUints[1:]
}

//UintPtr reads into **uint
func (r *Reader) UintPtr(v **uint) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUints[0]
	r.decUints = r.decUints[1:]
	*v = &i
}

//Uints reads into *[]uint
func (r *Reader) Uints(vs *[]uint) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decUints[:size]
	*vs = s
	r.decUints = r.decUints[size:]
}

//MUints reads into *[]uint
func (r *Reader) MUints(vs *[]uint) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decUints[:size]
	*vs = s
	r.decUints = r.decUints[size:]
}

//Int64 reads into *int64
func (r *Reader) Int64(v *int64) {
	*v = r.decInt64s[0]
	r.decInt64s = r.decInt64s[1:]
}

//Int64Ptr reads into **int64
func (r *Reader) Int64Ptr(v **int64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decInt64s[0]
	r.decInt64s = r.decInt64s[1:]
	*v = &i
}

//Int64s reads into *[]int64
func (r *Reader) Int64s(vs *[]int64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decInt64s[:size]
	*vs = s
	r.decInt64s = r.decInt64s[size:]
}

//MInt64s reads into *[]int64
func (r *Reader) MInt64s(vs *[]int64) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decInt64s[:size]
	*vs = s
	r.decInt64s = r.decInt64s[size:]
}

//Uint64 reads into *uint64
func (r *Reader) Uint64(v *uint64) {
	*v = r.decUint64s[0]
	r.decUint64s = r.decUint64s[1:]
}

//Uint64Ptr reads into **uint64
func (r *Reader) Uint64Ptr(v **uint64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUint64s[0]
	r.decUint64s = r.decUint64s[1:]
	*v = &i
}

//Uint64s reads into *[]uint64
func (r *Reader) Uint64s(vs *[]uint64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decUint64s[:size]
	*vs = s
	r.decUint64s = r.decUint64s[size:]
}


//MUint64s reads into *[]uint64
func (r *Reader) MUint64s(vs *[]uint64) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decUint64s[:size]
	*vs = s
	r.decUint64s = r.decUint64s[size:]
}

//Int32 reads into *int32
func (r *Reader) Int32(v *int32) {
	*v = r.decInt32s[0]
	r.decInt32s = r.decInt32s[1:]
}

//Int32Ptr reads into **int32
func (r *Reader) Int32Ptr(v **int32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decInt32s[0]
	r.decInt32s = r.decInt32s[1:]
	*v = &i
}

//Int32s reads into *[]int32
func (r *Reader) Int32s(vs *[]int32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decInt32s[:size]
	*vs = s
	r.decInt32s = r.decInt32s[size:]
}

//MInt32s reads into *[]int32
func (r *Reader) MInt32s(vs *[]int32) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decInt32s[:size]
	*vs = s
	r.decInt32s = r.decInt32s[size:]
}


//Uint32 reads into *uint32
func (r *Reader) Uint32(v *uint32) {
	*v = r.decUint32s[0]
	r.decUint32s = r.decUint32s[1:]
}

//Uint32Ptr reads into **uint32
func (r *Reader) Uint32Ptr(v **uint32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUint32s[0]
	r.decUint32s = r.decUint32s[1:]
	*v = &i
}

//Uint32s reads into  *[]uint32
func (r *Reader) Uint32s(vs *[]uint32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decUint32s[:size]
	*vs = s
	r.decUint32s = r.decUint32s[size:]
}


//Uint32s reads into  *[]uint32
func (r *Reader) MUint32s(vs *[]uint32) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decUint32s[:size]
	*vs = s
	r.decUint32s = r.decUint32s[size:]
}


//Int16 reads into *int16
func (r *Reader) Int16(v *int16) {
	*v = r.decInt16s[0]
	r.decInt16s = r.decInt16s[1:]
}

//Int16Ptr reads into **int16
func (r *Reader) Int16Ptr(v **int16) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decInt16s[0]
	r.decInt16s = r.decInt16s[1:]
	*v = &i
}

//Int16s reads into *[]int16
func (r *Reader) Int16s(vs *[]int16) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decInt16s[:size]
	*vs = s
	r.decInt16s = r.decInt16s[size:]
}

//Uint16 reads into *uint16
func (r *Reader) Uint16(v *uint16) {
	*v = r.decUint16s[0]
	r.decUint16s = r.decUint16s[1:]
}

//Uint16Ptr reads into **uint16
func (r *Reader) Uint16Ptr(v **uint16) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUint16s[0]
	r.decUint16s = r.decUint16s[1:]
	*v = &i
}

//Uint16s read into *[]uint16
func (r *Reader) Uint16s(vs *[]uint16) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decUint16s[:size]
	*vs = s
	r.decUint16s = r.decUint16s[size:]
}

//Int8 reads into *int8
func (r *Reader) Int8(v *int8) {
	*v = r.decInt8s[0]
	r.decInt8s = r.decInt8s[1:]
}

//Int8Ptr reads into **int8
func (r *Reader) Int8Ptr(v **int8) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decInt8s[0]
	r.decInt8s = r.decInt8s[1:]
	*v = &i
}

//Int8s reads into *[]int8
func (r *Reader) Int8s(vs *[]int8) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decInt8s[:size]
	*vs = s
	r.decInt8s = r.decInt8s[size:]
}

//Uint8 reads into *uint8
func (r *Reader) Uint8(v *uint8) {
	*v = r.decUint8s[0]
	r.decUint8s = r.decUint8s[1:]
}

//Uint8Ptr reads into **uint8
func (r *Reader) Uint8Ptr(v **uint8) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUint8s[0]
	r.decUint8s = r.decUint8s[1:]
	*v = &i
}

//Uint8s reads into *[]uint8
func (r *Reader) Uint8s(vs *[]uint8) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decUint8s[:size]
	*vs = s
	r.decUint8s = r.decUint8s[size:]
}

//MUint8s reads medium size slice (64k) into *[]uint8
func (r *Reader) MUint8s(vs *[]uint8) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	s := r.decUint8s[:size]
	*vs = s
	r.decUint8s = r.decUint8s[size:]
}


//Float64 reads into *float64
func (r *Reader) Float64(v *float64) {
	*v = r.decFloat64s[0]
	r.decFloat64s = r.decFloat64s[1:]
}

//Float64Ptr reads into **float64
func (r *Reader) Float64Ptr(v **float64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decFloat64s[0]
	r.decFloat64s = r.decFloat64s[1:]
	*v = &i
}

//Float64s reads into *[]float64
func (r *Reader) Float64s(vs *[]float64) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decFloat64s[:size]
	*vs = s
	r.decFloat64s = r.decFloat64s[size:]
}

//Float32 reads into *float32
func (r *Reader) Float32(v *float32) {
	*v = r.decFloat32s[0]
	r.decFloat32s = r.decFloat32s[1:]
}

//Float32Ptr reads into **float32
func (r *Reader) Float32Ptr(v **float32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decFloat32s[0]
	r.decFloat32s = r.decFloat32s[1:]
	*v = &i
}

//Float32s reads into *[]float32
func (r *Reader) Float32s(vs *[]float32) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	s := r.decFloat32s[:size]
	*vs = s
	r.decFloat32s = r.decFloat32s[size:]
}

//Bool reads into *bool
func (r *Reader) Bool(v *bool) {
	val := false
	i := r.decUint8s[0]
	r.decUint8s = r.decUint8s[1:]
	if i == 1 {
		val = true
	}
	*v = val
}

//BoolPtr reads into **bool
func (r *Reader) BoolPtr(v **bool) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	i := r.decUint8s[0]
	val := false
	r.decUint8s = r.decUint8s[1:]
	if i == 1 {
		val = true
	}
	*v = &val
}

//Bools reads into *[]bool
func (r *Reader) Bools(vs *[]bool) {
	size := int(r.Alloc())
	if size == 0 {
		return
	}
	var bools = make([]bool, size)
	for i := 0; i < size; i++ {
		bools[i] = r.decUint8s[i] == 1
	}
	r.decUint8s = r.decUint8s[size:]
	*vs = bools
}

//String reads into *string
func (r *Reader) String(v *string) {
	var bs []byte
	r.Uint8s(&bs)
	s := unsafeGetString(bs)
	*v = s
}

//StringPtr reads into **string
func (r *Reader) StringPtr(v **string) {
	var bs []byte
	r.Uint8s(&bs)
	s := unsafeGetString(bs)
	*v = &s
}

//Strings reads into *[]string
func (r *Reader) Strings(v *[]string) {
	size := r.Alloc()
	if size == 0 {
		return
	}
	var strings = make([]string, size)
	for i := 0; i < int(size); i++ {
		r.String(&strings[i])
	}
	*v = strings
}


//MString reads into *string
func (r *Reader) MString(v *string) {
	var bs []byte
	r.MUint8s(&bs)
	s := unsafeGetString(bs)
	*v = s
}

//MStringPtr reads into **string
func (r *Reader) MStringPtr(v **string) {
	var bs []byte
	r.MUint8s(&bs)
	s := unsafeGetString(bs)
	*v = &s
}

//MStrings reads into *[]string
func (r *Reader) MStrings(v *[]string) {
	size := r.MAlloc()
	if size == 0 {
		return
	}
	var strings = make([]string, size)
	for i := 0; i < int(size); i++ {
		r.MString(&strings[i])
	}
	*v = strings
}


//Time reads into *time.Time
func (r *Reader) Time(v *time.Time) {
	n := int64(0)
	r.Int64(&n)
	*v = time.Unix(0, n)
}

//TimePtr reads into **time.Time
func (r *Reader) TimePtr(v **time.Time) {
	var ptr *int64
	r.Int64Ptr(&ptr)
	if ptr == nil {
		return
	}
	t := time.Unix(0, *ptr)
	*v = &t
}

//Coder decodes coder
func (r *Reader) Coder(coder Decoder) error {
	size := r.Alloc()
	if allocator, ok := coder.(Allocator); ok {
		allocator.SetAlloc(size)
	}
	switch size {
	case NilSize, 0:
		return nil
	case 1:
		return coder.DecodeBinary(r)
	}
	for i := 0; i < int(size); i++ {
		if err := coder.DecodeBinary(r); err != nil {
			return err
		}
	}
	return nil
}

//FromBytes loads stream from bytes
func (r *Reader) FromBytes(data []byte) error {
	offset := 0
	offset = r.decAlloc.load(data, offset, codecAlloc)
	offset = r.decMAlloc.load(data, offset, codecMAlloc)
	offset = r.decInts.load(data, offset)
	offset = r.decFloat64s.load(data, offset)
	offset = r.decUint8s.load(data, offset)
	if data[offset] == codecEOF {
		return nil
	}
	offset = r.decInt32s.load(data, offset, codecInt32s)
	offset = r.decUint32s.load(data, offset)
	if data[offset] == codecEOF {
		return nil
	}
	offset = r.decFloat32s.load(data, offset)
	if data[offset] == codecEOF {
		return nil
	}
	offset = r.decUints.load(data, offset)
	offset = r.decInt64s.load(data, offset)
	offset = r.decUint64s.load(data, offset)
	offset = r.decInt16s.load(data, offset)
	offset = r.decUint16s.load(data, offset, codecUint16s)
	offset = r.decInt8s.load(data, offset)
	if data[offset] != codecEOF {
		return fmt.Errorf("corrupted bintly stream expected: %v, but had %v", codecEOF, data[offset])
	}
	return nil
}

func (r *Reader) anyReflect(v interface{}) error {
	rawType := reflect.TypeOf(v)
	if rawType.Kind() != reflect.Ptr {
		return fmt.Errorf("expected pointer, but had:%T", v)
	}
	rawType = rawType.Elem()
	value := reflect.ValueOf(v)
	isPointer := rawType.Kind() == reflect.Ptr
	if isPointer {
		rawType = rawType.Elem()
	}
	switch rawType.Kind() {
	case reflect.Struct:
		coder := structCoders.Get()
		defer structCoders.Put(coder)
		if err := coder.set(value, rawType); err != nil {
			return err
		}
		return r.Coder(coder)
	case reflect.Map:
		coder := mapCoders.Get()
		defer mapCoders.Put(coder)
		coder.set(value, rawType)
		return r.Coder(coder)
	case reflect.Slice:
		coder := sliceCoders.Get()
		defer sliceCoders.Put(coder)
		coder.set(value, rawType)
		return r.Coder(coder)
	default:
		//handles natives type aliases
		if nativeType := conv.MatchNative(rawType); nativeType != nil {
			native := reflect.New(*nativeType)
			if err := r.Any(native.Interface()); err != nil {
				return err
			}
			alias := native.Elem().Convert(rawType)
			if isPointer { //**T case
				actual := reflect.New(rawType)
				actual.Elem().Set(alias)
				value.Elem().Set(actual)
			} else {
				value.Elem().Set(alias)
			}
			return nil
		}
	}
	return fmt.Errorf("unsupproted readers type: %T", v)
}

func (s *decInts) load(data []byte, offset int) int {
	if data[offset] != codecInts {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Uint32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]int, size)
	GetInts(data[offset:], *s)
	offset += sizeIntInBytes * size
	return offset
}

func (s *decUints) load(data []byte, offset int) int {
	if data[offset] != codecUints {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Uint32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]uint, size)
	GetUints(data[offset:], *s)
	offset += sizeIntInBytes * size
	return offset
}

func (s *decInt64s) load(data []byte, offset int) int {
	if data[offset] != codecInt64s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]int64, size)
	GetInt64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset
}

func (s *decUint64s) load(data []byte, offset int) int {
	if data[offset] != codecUint64s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Uint32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]uint64, size)
	GetUint64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset
}

func (s *decInt32s) load(data []byte, offset int, codec uint8) int {
	if data[offset] != codec {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Uint32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]int32, size)
	GetInt32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset
}

func (s *decUint32s) load(data []byte, offset int) int {
	if data[offset] != codecUint32s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Uint32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]uint32, size)
	GetUint32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset
}

func (s *decInt16s) load(data []byte, offset int) int {
	if data[offset] != codecInt16s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]int16, size)
	GetInt16s(data[offset:], *s)
	offset += size16bitsInBytes * size
	return offset
}

func (s *decUint16s) load(data []byte, offset int, codec uint8) int {
	if data[offset] != codec {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]uint16, size)
	GetUint16s(data[offset:], *s)
	offset += size16bitsInBytes * size
	return offset
}

func (s *decInt8s) load(data []byte, offset int) int {
	if data[offset] != codecInt8s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]int8, size)
	GetInt8s(data[offset:], *s)
	offset += size8bitsInBytes * size
	return offset
}

func (s *decUint8s) load(data []byte, offset int) int {
	if data[offset] != codecUint8s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]uint8, size)
	GetUint8s(data[offset:], *s)
	offset += size8bitsInBytes * size
	return offset
}

func (s *decFloat64s) load(data []byte, offset int) int {
	if data[offset] != codecFloat64s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]float64, size)
	GetFloat64s(data[offset:], *s)
	offset += size64bitsInBytes * size
	return offset
}

func (s *decFloat32s) load(data []byte, offset int) int {
	if data[offset] != codecFloat32s {
		return offset
	}
	offset += size8bitsInBytes
	size := int(Int32(data[offset:]))
	offset += size32bitsInBytes
	*s = make([]float32, size)
	GetFloat32s(data[offset:], *s)
	offset += size32bitsInBytes * size
	return offset
}

//Readers represents readers pool
type Readers struct {
	sync.Pool
}

//Get returns a readers
func (p *Readers) Get() *Reader {
	codec := p.Pool.Get()
	return codec.(*Reader)
}

//NewReaders creates a readers pool
func NewReaders() *Readers {
	return &Readers{
		Pool: sync.Pool{
			New: func() interface{} {
				return &Reader{}
			},
		},
	}
}


<|start_filename|>codegen/test_data/basic_struct/message.go<|end_filename|>
package basic_struct

type Message struct {
	A1 int
	B1 *string
	C1 []string
	//D1 uint
	//E1 *uint
	//F1 []uint
	//
	//A2 int64
	//B2 *int64
	//C2 []int64
	//D2 uint64
	//E2 *uint64
	//F2 []uint64
	//
	//A3 int32
	//B3 *int32
	//C3 []int32
	//D3 uint32
	//E3 *uint32
	//F3 []uint32
	//
	//A4 int16
	//B4 *int16
	//C4 []int16
	//D4 uint16
	//E4 *uint16
	//F4 []uint16
	//A5 int8
	//B5 *int8
	//C5 []int8
	//D5 uint8
	//E5 *uint8
	//F5 []uint8
	//G  bool
	//H  string
}


<|start_filename|>ints_test.go<|end_filename|>
package bintly

import (
	"encoding/binary"
	"github.com/stretchr/testify/assert"
	"math"
	"math/rand"
	"testing"
)

func Test_PutInts(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		ints        []int
	}{
		{
			description: "tiny slice",
			ints:        []int{math.MaxInt32, 0, 10, math.MaxUint16, math.MaxUint32, math.MaxUint8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "medium slice 2",
			size:        100,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.ints) == 0 {
			useCase.ints = make([]int, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.ints[i] = int(rand.Int31())
			}
		}
		var data = make([]byte, 8*len(useCase.ints))
		PutInts(data, useCase.ints)
		actual := Ints(data)
		assert.EqualValues(t, useCase.ints, actual, useCase.description)
	}
}

func Test_PutUint64s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		uints       []uint64
	}{
		{
			description: "tiny slice",
			uints:       []uint64{math.MaxUint64, 0, 10, math.MaxUint16, math.MaxUint32, math.MaxUint8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.uints) == 0 {
			useCase.uints = make([]uint64, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.uints[i] = rand.Uint64()
			}
		}
		var data = make([]byte, 8*len(useCase.uints))
		PutUint64s(data, useCase.uints)
		actual := Uint64s(data)
		assert.EqualValues(t, useCase.uints, actual, useCase.description)
	}
}

func BenchmarkPutUint64s(b *testing.B) {
	var data = make([]byte, len(uint64slice)*8)
	for i := 0; i < b.N; i++ {
		PutUint64s(data, uint64slice)
		actual := Uint64s(data)
		for j, v := range uint64slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkPutUint64s_Binary(b *testing.B) {
	var data = make([]byte, len(uint64slice)*8)
	coder := binary.LittleEndian
	for i := 0; i < b.N; i++ {
		for j, v := range uint64slice {
			coder.PutUint64(data[j*8:], v)
		}
		var actual = make([]uint64, len(uint64slice))
		for j := range uint64slice {
			actual[j] = coder.Uint64(data[j*8:])
		}
		for j, v := range uint64slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkGetUint64s(b *testing.B) {
	var data = make([]byte, len(uint64slice)*8)
	var actual = make([]uint64, len(uint64slice))
	for i := 0; i < b.N; i++ {
		PutUint64s(data, uint64slice)
		GetUint64s(data, actual)
		for j, v := range uint64slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkGetUint64s_Binary(b *testing.B) {
	var data = make([]byte, len(uint64slice)*8)
	coder := binary.LittleEndian
	var actual = make([]uint64, len(uint64slice))
	for i := 0; i < b.N; i++ {
		for j, v := range uint64slice {
			coder.PutUint64(data[j*8:], v)
		}
		for j := range uint64slice {
			actual[j] = coder.Uint64(data[j*8:])
		}
		for j, v := range uint64slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func Test_PutUint32s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		uints       []uint32
	}{
		{
			description: "tiny slice",
			uints:       []uint32{math.MaxUint32, 0, 10, math.MaxUint16, math.MaxUint32, math.MaxUint8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.uints) == 0 {
			useCase.uints = make([]uint32, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.uints[i] = rand.Uint32()
			}
		}
		var data = make([]byte, 4*len(useCase.uints))
		PutUint32s(data, useCase.uints)
		actual := Uint32s(data)
		assert.EqualValues(t, useCase.uints, actual, useCase.description)
	}
}

func BenchmarkPutUint32s(b *testing.B) {
	var data = make([]byte, len(uint32Slice)*4)
	for i := 0; i < b.N; i++ {
		PutUint32s(data, uint32Slice)
		actual := Uint32s(data)
		for j, v := range uint32Slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkPutUint32s_Binary(b *testing.B) {
	var data = make([]byte, len(uint32Slice)*4)
	coder := binary.LittleEndian
	for i := 0; i < b.N; i++ {
		for j, v := range uint32Slice {
			coder.PutUint32(data[j*4:], v)
		}
		var actual = make([]uint32, len(uint32Slice))
		for j := range uint32Slice {
			actual[j] = coder.Uint32(data[j*4:])
		}
		for j, v := range uint32Slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkGetUint32s(b *testing.B) {
	var data = make([]byte, len(uint32Slice)*4)
	var actual = make([]uint32, len(uint32Slice))
	for i := 0; i < b.N; i++ {
		PutUint32s(data, uint32Slice)
		GetUint32s(data, actual)
		for j, v := range uint32Slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func BenchmarkGetUint32s_Binary(b *testing.B) {
	var data = make([]byte, len(uint32Slice)*8)
	coder := binary.LittleEndian
	var actual = make([]uint32, len(uint32Slice))
	for i := 0; i < b.N; i++ {
		for j, v := range uint32Slice {
			coder.PutUint32(data[j*4:], v)
		}
		for j := range uint32Slice {
			actual[j] = coder.Uint32(data[j*4:])
		}
		for j, v := range uint32Slice {
			if v != actual[j] {
				assert.EqualValues(b, v, actual[j])
			}
		}
	}
}

func Test_PutUint16s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		uints       []uint16
	}{
		{
			description: "tiny slice",
			uints:       []uint16{math.MaxUint16, 0, 10, math.MaxUint16, math.MaxUint16, math.MaxUint8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.uints) == 0 {
			useCase.uints = make([]uint16, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.uints[i] = uint16(rand.Uint32() % math.MaxUint16)
			}
		}
		var data = make([]byte, 2*len(useCase.uints))
		PutUint16s(data, useCase.uints)
		actual := Uint16s(data)
		assert.EqualValues(t, useCase.uints, actual, useCase.description)
	}
}

func Test_PutInt64s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		ints        []int64
	}{
		{
			description: "tiny slice",
			ints:        []int64{math.MaxInt64, 0, 10, math.MaxInt16, math.MaxInt32, math.MaxInt8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.ints) == 0 {
			useCase.ints = make([]int64, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.ints[i] = rand.Int63()
			}
		}
		var data = make([]byte, 8*len(useCase.ints))
		PutInt64s(data, useCase.ints)
		actual := Int64s(data)
		assert.EqualValues(t, useCase.ints, actual, useCase.description)
	}
}

func Test_PutInt32s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		ints        []int32
	}{
		{
			description: "tiny slice",
			ints:        []int32{math.MaxInt32, 0, 10, math.MaxInt16, math.MaxInt32, math.MaxInt8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.ints) == 0 {
			useCase.ints = make([]int32, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.ints[i] = rand.Int31()
			}
		}
		var data = make([]byte, 4*len(useCase.ints))
		PutInt32s(data, useCase.ints)
		actual := Int32s(data)
		assert.EqualValues(t, useCase.ints, actual, useCase.description)
	}
}

func Test_PutInt16s(t *testing.T) {
	var useCases = []struct {
		description string
		size        int
		ints        []int16
	}{
		{
			description: "tiny slice",
			ints:        []int16{math.MaxInt16, 0, 10, math.MaxInt16, math.MaxInt16, math.MaxInt8},
		},
		{
			description: "small slice",
			size:        257,
		},
		{
			description: "medium slice",
			size:        3 * 1024,
		},
		{
			description: "large slice",
			size:        1024 * 128,
		},
	}

	for _, useCase := range useCases {
		if len(useCase.ints) == 0 {
			useCase.ints = make([]int16, useCase.size)
			for i := 0; i < useCase.size; i++ {
				useCase.ints[i] = int16(rand.Int31() % math.MaxInt16)
			}
		}
		var data = make([]byte, 2*len(useCase.ints))
		PutInt16s(data, useCase.ints)
		actual := Int16s(data)
		assert.EqualValues(t, useCase.ints, actual, useCase.description)
	}
}


<|start_filename|>const.go<|end_filename|>
package bintly

import "math/bits"

const (
	sizeIntInBytes    = bits.UintSize / 8
	size64bitsInBytes = 8
	size32bitsInBytes = 4
	size16bitsInBytes = 2
	size8bitsInBytes  = 1
	//represents nil size
	NilSize = -1
)


<|start_filename|>codec.go<|end_filename|>
package bintly

const (
	codecEOF = uint8(iota)
	codecAlloc  //alloc upto 2Gb
	codecMAlloc //medium size alloc upto 64k
	codecInts
	codecUints
	codecInt64s
	codecUint64s
	codecInt32s
	codecUint32s
	codecInt16s
	codecUint16s
	codecInt8s
	codecUint8s
	codecFloat64s
	codecFloat32s
)
