<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/encoder.go                                          *
 *                                                        *
 * hprose encoder for Go.                                 *
 *                                                        *
 * LastModified: Aug 23, 2016                             *
 * Author: <NAME> <<EMAIL>>                  *
 *                                                        *
\**********************************************************/

package io

import (
	"reflect"
	"unsafe"

	"github.com/hprose/hprose-golang/util"
)

type valueEncoder func(writer *Writer, v reflect.Value)

var valueEncoders []valueEncoder

func nilEncoder(writer *Writer, v reflect.Value) {
	writer.WriteNil()
}

func boolEncoder(writer *Writer, v reflect.Value) {
	writer.WriteBool(v.Bool())
}

func intEncoder(writer *Writer, v reflect.Value) {
	writer.WriteInt(v.Int())
}

func uintEncoder(writer *Writer, v reflect.Value) {
	writer.WriteUint(v.Uint())
}

func float32Encoder(writer *Writer, v reflect.Value) {
	writer.WriteFloat(v.Float(), 32)
}

func float64Encoder(writer *Writer, v reflect.Value) {
	writer.WriteFloat(v.Float(), 64)
}

func complex64Encoder(writer *Writer, v reflect.Value) {
	writer.WriteComplex64(complex64(v.Complex()))
}

func complex128Encoder(writer *Writer, v reflect.Value) {
	writer.WriteComplex128(v.Complex())
}

func interfaceEncoder(writer *Writer, v reflect.Value) {
	if v.IsNil() {
		writer.WriteNil()
		return
	}
	e := v.Elem()
	valueEncoders[e.Kind()](writer, e)
}

func arrayEncoder(writer *Writer, v reflect.Value) {
	writer.SetRef(nil)
	writeArray(writer, v)
}

func sliceEncoder(writer *Writer, v reflect.Value) {
	writer.SetRef(nil)
	writeSlice(writer, v)
}

func stringEncoder(writer *Writer, v reflect.Value) {
	writer.WriteString(v.String())
}

func arrayPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		writeArray(writer, v)
	}
}

func mapPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		//writeMap(writer, v)
	}
}

func slicePtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		writeSlice(writer, v)
	}
}

func stringPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	str := v.String()
	length := util.UTF16Length(str)
	s := writer.Stream
	switch {
	case length == 0:
		s.WriteByte(TagEmpty)
	case length < 0:
		writer.WriteBytes(*(*[]byte)(unsafe.Pointer(&str)))
	case length == 1:
		s.WriteByte(TagUTF8Char)
		s.WriteString(str)
	default:
		if !writer.WriteRef(addr) {
			writer.SetRef(addr)
			writeString(s, str, length)
		}
	}
}

func structPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if v.Type().PkgPath() == "big" {
		v.Interface().(Marshaler).MarshalHprose(writer)
		return
	}
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		//writeStruct(writer, v)
	}
}

func ptrEncoder(writer *Writer, v reflect.Value) {
	if v.IsNil() {
		writer.WriteNil()
		return
	}
	e := v.Elem()
	kind := e.Kind()
	switch kind {
	case reflect.Array:
		arrayPtrEncoder(writer, e, v.Pointer())
	case reflect.Map:
		mapPtrEncoder(writer, e, v.Pointer())
	case reflect.Slice:
		slicePtrEncoder(writer, e, v.Pointer())
	case reflect.String:
		stringPtrEncoder(writer, e, v.Pointer())
	case reflect.Struct:
		structPtrEncoder(writer, e, v.Pointer())
	default:
		valueEncoders[kind](writer, e)
	}
}

func init() {
	valueEncoders = []valueEncoder{
		reflect.Invalid:       nilEncoder,
		reflect.Bool:          boolEncoder,
		reflect.Int:           intEncoder,
		reflect.Int8:          intEncoder,
		reflect.Int16:         intEncoder,
		reflect.Int32:         intEncoder,
		reflect.Int64:         intEncoder,
		reflect.Uint:          uintEncoder,
		reflect.Uint8:         uintEncoder,
		reflect.Uint16:        uintEncoder,
		reflect.Uint32:        uintEncoder,
		reflect.Uint64:        uintEncoder,
		reflect.Uintptr:       uintEncoder,
		reflect.Float32:       float32Encoder,
		reflect.Float64:       float64Encoder,
		reflect.Complex64:     complex64Encoder,
		reflect.Complex128:    complex128Encoder,
		reflect.Array:         arrayEncoder,
		reflect.Chan:          nilEncoder,
		reflect.Func:          nilEncoder,
		reflect.Interface:     interfaceEncoder,
		reflect.Map:           nilEncoder,
		reflect.Ptr:           ptrEncoder,
		reflect.Slice:         sliceEncoder,
		reflect.String:        stringEncoder,
		reflect.Struct:        nilEncoder,
		reflect.UnsafePointer: nilEncoder,
	}
}<commit_msg>Added structEncoder<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/encoder.go                                          *
 *                                                        *
 * hprose encoder for Go.                                 *
 *                                                        *
 * LastModified: Aug 23, 2016                             *
 * Author: <NAME> <<EMAIL>>                  *
 *                                                        *
\**********************************************************/

package io

import (
	"reflect"
	"unsafe"

	"github.com/hprose/hprose-golang/util"
)

type valueEncoder func(writer *Writer, v reflect.Value)

var valueEncoders []valueEncoder

func nilEncoder(writer *Writer, v reflect.Value) {
	writer.WriteNil()
}

func boolEncoder(writer *Writer, v reflect.Value) {
	writer.WriteBool(v.Bool())
}

func intEncoder(writer *Writer, v reflect.Value) {
	writer.WriteInt(v.Int())
}

func uintEncoder(writer *Writer, v reflect.Value) {
	writer.WriteUint(v.Uint())
}

func float32Encoder(writer *Writer, v reflect.Value) {
	writer.WriteFloat(v.Float(), 32)
}

func float64Encoder(writer *Writer, v reflect.Value) {
	writer.WriteFloat(v.Float(), 64)
}

func complex64Encoder(writer *Writer, v reflect.Value) {
	writer.WriteComplex64(complex64(v.Complex()))
}

func complex128Encoder(writer *Writer, v reflect.Value) {
	writer.WriteComplex128(v.Complex())
}

func interfaceEncoder(writer *Writer, v reflect.Value) {
	if v.IsNil() {
		writer.WriteNil()
		return
	}
	e := v.Elem()
	valueEncoders[e.Kind()](writer, e)
}

func arrayEncoder(writer *Writer, v reflect.Value) {
	writer.SetRef(nil)
	writeArray(writer, v)
}

func sliceEncoder(writer *Writer, v reflect.Value) {
	writer.SetRef(nil)
	writeSlice(writer, v)
}

func stringEncoder(writer *Writer, v reflect.Value) {
	writer.WriteString(v.String())
}

func structEncoder(writer *Writer, v reflect.Value) {
	structPtrEncoder(writer, v.Addr())
}

func arrayPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		writeArray(writer, v)
	}
}

func mapPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		//writeMap(writer, v)
	}
}

func slicePtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		writeSlice(writer, v)
	}
}

func stringPtrEncoder(writer *Writer, v reflect.Value, addr uintptr) {
	str := v.String()
	length := util.UTF16Length(str)
	s := writer.Stream
	switch {
	case length == 0:
		s.WriteByte(TagEmpty)
	case length < 0:
		writer.WriteBytes(*(*[]byte)(unsafe.Pointer(&str)))
	case length == 1:
		s.WriteByte(TagUTF8Char)
		s.WriteString(str)
	default:
		if !writer.WriteRef(addr) {
			writer.SetRef(addr)
			writeString(s, str, length)
		}
	}
}

func structPtrEncoder(writer *Writer, v reflect.Value) {
	if v.Type().PkgPath() == "big" {
		v.Interface().(Marshaler).MarshalHprose(writer)
		return
	}
	addr := v.Pointer()
	if !writer.WriteRef(addr) {
		writer.SetRef(addr)
		//writeStruct(writer, v)
	}
}

func ptrEncoder(writer *Writer, v reflect.Value) {
	if v.IsNil() {
		writer.WriteNil()
		return
	}
	e := v.Elem()
	kind := e.Kind()
	switch kind {
	case reflect.Array:
		arrayPtrEncoder(writer, e, v.Pointer())
	case reflect.Map:
		mapPtrEncoder(writer, e, v.Pointer())
	case reflect.Slice:
		slicePtrEncoder(writer, e, v.Pointer())
	case reflect.String:
		stringPtrEncoder(writer, e, v.Pointer())
	case reflect.Struct:
		structPtrEncoder(writer, v)
	default:
		valueEncoders[kind](writer, e)
	}
}

func init() {
	valueEncoders = []valueEncoder{
		reflect.Invalid:       nilEncoder,
		reflect.Bool:          boolEncoder,
		reflect.Int:           intEncoder,
		reflect.Int8:          intEncoder,
		reflect.Int16:         intEncoder,
		reflect.Int32:         intEncoder,
		reflect.Int64:         intEncoder,
		reflect.Uint:          uintEncoder,
		reflect.Uint8:         uintEncoder,
		reflect.Uint16:        uintEncoder,
		reflect.Uint32:        uintEncoder,
		reflect.Uint64:        uintEncoder,
		reflect.Uintptr:       uintEncoder,
		reflect.Float32:       float32Encoder,
		reflect.Float64:       float64Encoder,
		reflect.Complex64:     complex64Encoder,
		reflect.Complex128:    complex128Encoder,
		reflect.Array:         arrayEncoder,
		reflect.Chan:          nilEncoder,
		reflect.Func:          nilEncoder,
		reflect.Interface:     interfaceEncoder,
		reflect.Map:           nilEncoder,
		reflect.Ptr:           ptrEncoder,
		reflect.Slice:         sliceEncoder,
		reflect.String:        stringEncoder,
		reflect.Struct:        structEncoder,
		reflect.UnsafePointer: nilEncoder,
	}
}
{'fraction_non_alphanumeric': 0.16003443657929978, 'fraction_numerical': 0.01224411708436962, 'mean_word_length': 2.370406189555126, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5579860', 'n_tokens_mistral': 3327, 'n_tokens_neox': 3090, 'n_words': 619}