func calculateInfoFromIntLength(l int) (info byte, err error) {
	if l < int(cborSmallInt) {
		info = byte(l)
	} else {
		if info, err = infoHelper(uint(l)); err != nil {
			return 0, err
		}
	}
	return info, nil
}
helper function that calculates the size
of the info byte depending on the given length
package cbor
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"math/big"
	"reflect"
	"time"
	"unicode"
	"unsafe"
)
type handleEncFn handleDecFn
type Encoder struct {
	composer  *Composer
	canonical bool
	strict    bool
}
func NewEncoder(w io.Writer, options ...func(*Encoder)) *Encoder {
	e := &Encoder{composer: &Composer{w: w}, strict: false}
	if len(options) > 0 {
		for _, option := range options {
			option(e)
		}
	}
	return e
}
func (enc *Encoder) isValidPointer(t unsafe.Pointer) bool {
	if t == nil {
		enc.encodeNil()
		return false
	}
	return true
}
func (enc *Encoder) Encode(v interface{}) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()
	switch t := v.(type) {
	case nil:
		enc.encodeNil()
	case bool:
		enc.encodeBool(t)
	case uint8:
		enc.encodeUint(uint64(t))
	case int8:
		enc.encodeInt(int64(t))
	case uint16:
		enc.encodeUint(uint64(t))
	case int16:
		enc.encodeInt(int64(t))
	case uint32:
		enc.encodeUint(uint64(t))
	case int32:
		enc.encodeInt(int64(t))
	case uint64:
		enc.encodeUint(t)
	case int64:
		enc.encodeInt(t)
	case uint:
		enc.encodeUint(uint64(t))
	case int:
		enc.encodeInt(int64(t))
	case float16:
		enc.encodeFloat16(t)
	case float32:
		enc.encodeFloat32(t)
	case float64:
		enc.encodeFloat64(t)
	case big.Int:
		if t.Sign() < 0 {
			enc.encodeBigInt(t)
		} else {
			enc.encodeBigUint(t)
		}
	case time.Time:
		enc.encodeEpochDateTime(t)
	case big.Rat:
		enc.encodeBigFloat(t)
	case []uint8:
		enc.encodeByteString(t)
	case string:
		enc.encodeTextString(t)
	case *bool:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeBool(*t)
		}
	case *uint8:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeUint(uint64(*t))
		}
	case *int8:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeInt(int64(*t))
		}
	case *uint16:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeUint(uint64(*t))
		}
	case *int16:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeInt(int64(*t))
		}
	case *uint32:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeUint(uint64(*t))
		}
	case *int32:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeInt(int64(*t))
		}
	case *uint64:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeUint(*t)
		}
	case *int64:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeInt(*t)
		}
	case *uint:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeUint(uint64(*t))
		}
	case *int:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeInt(int64(*t))
		}
	case *float16:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeFloat16(*t)
		}
	case *float32:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeFloat32(*t)
		}
	case *float64:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeFloat64(*t)
		}
	case *big.Int:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			if t.Sign() < 0 {
				enc.encodeBigInt(*t)
			} else {
				enc.encodeBigUint(*t)
			}
		}
	case *time.Time:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeEpochDateTime(*t)
		}
	case *big.Rat:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeBigFloat(*t)
		}
	case *[]uint8:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeByteString(*t)
		}
	case *string:
		if enc.isValidPointer(unsafe.Pointer(t)) {
			enc.encodeTextString(*t)
		}
	case reflect.Value:
		enc.encode(t, v)
	default:
		enc.encode(reflect.ValueOf(v), v)
	}
	return nil
}
func (enc *Encoder) encode(rv reflect.Value, vs ...interface{}) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = errors.New(fmt.Sprint(r))
		}
	}()
	for rv.Kind() == reflect.Ptr {
		if rv.IsNil() {
			enc.encodeNil()
			return
		}
		rv = rv.Elem()
	}
	if !rv.IsValid() {
		enc.encodeNil()
		return
	}
	var v interface{} = rv.Interface()
	if len(vs) > 0 {
		v = vs[0]
	}
	switch rv.Type().Kind() {
	case reflect.Bool:
		err = enc.composer.composeBoolean(v.(bool))
	case reflect.Uint8:
		_, err = enc.composer.composeUint(uint64(v.(uint8)))
	case reflect.Uint16:
		_, err = enc.composer.composeUint(uint64(v.(uint16)))
	case reflect.Uint32:
		_, err = enc.composer.composeUint(uint64(v.(uint32)))
	case reflect.Uint64:
		_, err = enc.composer.composeUint(v.(uint64))
	case reflect.Uint:
		_, err = enc.composer.composeUint(uint64(v.(uint)))
	case reflect.Int8:
		_, err = enc.composer.composeInt(int64(v.(int8)))
	case reflect.Int16:
		_, err = enc.composer.composeInt(int64(v.(int16)))
	case reflect.Int32:
		_, err = enc.composer.composeInt(int64(v.(int32)))
	case reflect.Int64:
		_, err = enc.composer.composeInt(v.(int64))
	case reflect.Int:
		_, err = enc.composer.composeInt(int64(v.(int)))
	case reflect.Float32:
		err = enc.composer.composeFloat32(v.(float32))
	case reflect.Float64:
		err = enc.composer.composeFloat64(v.(float64))
	case reflect.String:
		enc.encodeTextString(v.(string))
	case reflect.Invalid:
		err = enc.composer.composeNil()
	case reflect.Slice, reflect.Array:
		enc.encodeSlice(rv)
	case reflect.Map:
		enc.encodeMap(rv)
	case reflect.Struct:
		enc.encodeStruct(rv)
	}
	return err
}
func (enc *Encoder) encodeNil() {
	if err := enc.composer.composeNil(); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeBool(v bool) {
	if err := enc.composer.composeBoolean(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeInt(v int64) {
	if _, err := enc.composer.composeInt(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeUint(v uint64) {
	if _, err := enc.composer.composeUint(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeFloat16(v float16) {
	if err := enc.composer.composeFloat16(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeFloat32(v float32) {
	if err := enc.composer.composeFloat32(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeFloat64(v float64) {
	if err := enc.composer.composeFloat64(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeByteString(v []byte) {
	if err := enc.composer.composeBytes(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeBigUint(v big.Int) {
	if err := enc.composer.composeBigUint(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeBigInt(v big.Int) {
	if err := enc.composer.composeBigInt(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeEpochDateTime(v time.Time) {
	if err := enc.composer.composeEpochDateTime(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeBigFloat(v big.Rat) {
	if err := enc.composer.composeBigFloat(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeTextString(v string) {
	if err := enc.composer.composeString(v); err != nil {
		panic(err)
	}
}
func (enc *Encoder) encodeSlice(rv reflect.Value) {
	etp := rv.Type().Elem()
	if etp.Kind() == reflect.Uint8 {
		enc.encodeByteString(rv.Bytes())
		return
	}
	l := rv.Len()
	info, err := calculateInfoFromIntLength(l)
	if err != nil {
		panic(err)
	}
	if err := enc.composer.composeInformation(cborDataArray, info); err != nil {
		panic(err)
	}
	if info > cborSmallInt {
		enc.encodeUint(uint64(l))
	}
	for i := 0; i < l; i++ {
		if err := enc.encode(rv.Index(i)); err != nil {
			panic(err)
		}
	}
}
func (enc *Encoder) encodeMap(rv reflect.Value) {
	l := rv.Len()
	info, err := calculateInfoFromIntLength(l)
	if err != nil {
		panic(err)
	}
	if err := enc.composer.composeInformation(cborDataMap, info); err != nil {
		panic(err)
	}
	if info > cborSmallInt {
		enc.encodeUint(uint64(l))
	}
	for _, key := range rv.MapKeys() {
		if err := enc.encode(key); err != nil {
			panic(err)
		}
		if err := enc.encode(rv.MapIndex(key)); err != nil {
			panic(err)
		}
	}
}
func (enc *Encoder) encodeStruct(rv reflect.Value, array ...bool) {
	buf := bytes.NewBuffer(nil)
	w := enc.composer.w
	enc.composer.w = buf
	exportedFields := 0
	numfields := rv.NumField()
	for i := 0; i < numfields; i++ {
		field := rv.Type().Field(i)
		key := field.Name
		if unicode.IsUpper(rune(key[0])) {
			tag := field.Tag.Get("cbor")
			if tag != "" {
				if tag == "-" {
					continue
				}
				key = tag
			}
			exportedFields++
			enc.encodeTextString(key)
			if err := enc.encode(rv.Field(i)); err != nil {
				panic(err)
			}
		}
	}
	enc.composer.w = w
	var info byte
	if len(array) > 0 && array[0] {
		info, _ = calculateInfoFromIntLength(exportedFields * 2)
	} else {
		info, _ = calculateInfoFromIntLength(exportedFields)
	}
	if err := enc.composer.composeInformation(cborDataMap, info); err != nil {
		panic(err)
	}
	if _, err := enc.composer.write(buf.Bytes()); err != nil {
		panic(err)
	}
}