package msgpack
import (
)
var errorType = reflect.TypeOf((*error)(nil)).Elem()
var (
customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem()
customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem()
)
var (
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
)
var (
binaryMarshalerType = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
binaryUnmarshalerType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
)
var (
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
type (
encoderFunc func(*Encoder, reflect.Value) error
decoderFunc func(*Decoder, reflect.Value) error
)
var (
typeEncMap sync.Map
typeDecMap sync.Map
)
func ( interface{}, encoderFunc, decoderFunc) {
:= reflect.TypeOf()
if != nil {
typeEncMap.Store(, )
}
if != nil {
typeDecMap.Store(, )
}
}
const defaultStructTag = "msgpack"
var structs = newStructCache()
type structCache struct {
m sync.Map
}
type structCacheKey struct {
tag string
typ reflect.Type
}
func () *structCache {
return new(structCache)
}
func ( *structCache) ( reflect.Type, string) *fields {
:= structCacheKey{tag: , typ: }
if , := .m.Load(); {
return .(*fields)
}
:= getFields(, )
.m.Store(, )
return
}
type field struct {
name string
index []int
omitEmpty bool
encoder encoderFunc
decoder decoderFunc
}
func ( *field) ( reflect.Value, bool) bool {
, := fieldByIndex(, .index)
if ! {
return true
}
return (.omitEmpty || ) && isEmptyValue()
}
func ( *field) ( *Encoder, reflect.Value) error {
, := fieldByIndex(, .index)
if ! {
return .EncodeNil()
}
return .encoder(, )
}
func ( *field) ( *Decoder, reflect.Value) error {
:= fieldByIndexAlloc(, .index)
return .decoder(, )
}
type fields struct {
Type reflect.Type
Map map[string]*field
List []*field
AsArray bool
hasOmitEmpty bool
}
func ( reflect.Type) *fields {
return &fields{
Type: ,
Map: make(map[string]*field, .NumField()),
List: make([]*field, 0, .NumField()),
}
}
func ( *fields) ( *field) {
.warnIfFieldExists(.name)
.Map[.name] =
.List = append(.List, )
if .omitEmpty {
.hasOmitEmpty = true
}
}
func ( *fields) ( string) {
if , := .Map[]; {
log.Printf("msgpack: %s already has field=%s", .Type, )
}
}
func ( *fields) ( reflect.Value, bool) []*field {
if !.hasOmitEmpty && ! {
return .List
}
:= make([]*field, 0, len(.List))
for , := range .List {
if !.Omit(, ) {
= append(, )
}
}
return
}
func ( reflect.Type, string) *fields {
:= newFields()
var bool
for := 0; < .NumField(); ++ {
:= .Field()
:= .Tag.Get(defaultStructTag)
if == "" && != "" {
= .Tag.Get()
}
:= tagparser.Parse()
if .Name == "-" {
continue
}
if .Name == "_msgpack" {
.AsArray = .HasOption("as_array") || .HasOption("asArray")
if .HasOption("omitempty") {
= true
}
}
if .PkgPath != "" && !.Anonymous {
continue
}
:= &field{
name: .Name,
index: .Index,
omitEmpty: || .HasOption("omitempty"),
}
if .HasOption("intern") {
switch .Type.Kind() {
case reflect.Interface:
.encoder = encodeInternedInterfaceValue
.decoder = decodeInternedInterfaceValue
case reflect.String:
.encoder = encodeInternedStringValue
.decoder = decodeInternedStringValue
default:
:= fmt.Errorf("msgpack: intern strings are not supported on %s", .Type)
panic()
}
} else {
.encoder = getEncoder(.Type)
.decoder = getDecoder(.Type)
}
if .name == "" {
.name = .Name
}
if .Anonymous && !.HasOption("noinline") {
:= .HasOption("inline")
if {
inlineFields(, .Type, , )
} else {
= shouldInline(, .Type, , )
}
if {
if , := .Map[.name]; {
log.Printf("msgpack: %s already has field=%s", .Type, .name)
}
.Map[.name] =
continue
}
}
.Add()
if , := .Options["alias"]; {
.warnIfFieldExists()
.Map[] =
}
}
return
}
var (
encodeStructValuePtr uintptr
decodeStructValuePtr uintptr
)
func () {
encodeStructValuePtr = reflect.ValueOf(encodeStructValue).Pointer()
decodeStructValuePtr = reflect.ValueOf(decodeStructValue).Pointer()
}
func ( *fields, reflect.Type, *field, string) {
:= getFields(, ).List
for , := range {
if , := .Map[.name]; {
continue
}
.index = append(.index, .index...)
.Add()
}
}
func ( *fields, reflect.Type, *field, string) bool {
var encoderFunc
var decoderFunc
if .Kind() == reflect.Struct {
= .encoder
= .decoder
} else {
for .Kind() == reflect.Ptr {
= .Elem()
= getEncoder()
= getDecoder()
}
if .Kind() != reflect.Struct {
return false
}
}
if reflect.ValueOf().Pointer() != encodeStructValuePtr {
return false
}
if reflect.ValueOf().Pointer() != decodeStructValuePtr {
return false
}
:= getFields(, ).List
for , := range {
if , := .Map[.name]; {
return false
}
}
for , := range {
.index = append(.index, .index...)
.Add()
}
return true
}
type isZeroer interface {
IsZero() bool
}
func ( reflect.Value) bool {
:= .Kind()
for == reflect.Interface {
if .IsNil() {
return true
}
= .Elem()
= .Kind()
}
if , := .Interface().(isZeroer); {
return nilable() && .IsNil() || .IsZero()
}
switch {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return .Len() == 0
case reflect.Bool:
return !.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return .Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return .Uint() == 0
case reflect.Float32, reflect.Float64:
return .Float() == 0
case reflect.Ptr:
return .IsNil()
default:
return false
}
}
func ( reflect.Value, []int) ( reflect.Value, bool) {
if len() == 1 {
return .Field([0]), true
}
for , := range {
if > 0 {
if .Kind() == reflect.Ptr {
if .IsNil() {
return , false
}
= .Elem()
}
}
= .Field()
}
return , true
}
func ( reflect.Value, []int) reflect.Value {
if len() == 1 {
return .Field([0])
}
for , := range {
if > 0 {
var bool
, = indirectNil()
if ! {
return
}
}
= .Field()
}
return
}
func ( reflect.Value) (reflect.Value, bool) {
if .Kind() == reflect.Ptr {
if .IsNil() {
if !.CanSet() {
return , false
}
:= .Type().Elem()
if .Kind() != reflect.Struct {
return , false
}
.Set(reflect.New())
}
= .Elem()
}
return , true
}