vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
changeset 256 6d9efbef00a9
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
       
     1 // Copyright 2018 The Go Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style
       
     3 // license that can be found in the LICENSE file.
       
     4 
       
     5 package impl
       
     6 
       
     7 import (
       
     8 	"fmt"
       
     9 	"math"
       
    10 	"reflect"
       
    11 	"sync"
       
    12 
       
    13 	"google.golang.org/protobuf/internal/flags"
       
    14 	pref "google.golang.org/protobuf/reflect/protoreflect"
       
    15 	preg "google.golang.org/protobuf/reflect/protoregistry"
       
    16 )
       
    17 
       
    18 type fieldInfo struct {
       
    19 	fieldDesc pref.FieldDescriptor
       
    20 
       
    21 	// These fields are used for protobuf reflection support.
       
    22 	has        func(pointer) bool
       
    23 	clear      func(pointer)
       
    24 	get        func(pointer) pref.Value
       
    25 	set        func(pointer, pref.Value)
       
    26 	mutable    func(pointer) pref.Value
       
    27 	newMessage func() pref.Message
       
    28 	newField   func() pref.Value
       
    29 }
       
    30 
       
    31 func fieldInfoForMissing(fd pref.FieldDescriptor) fieldInfo {
       
    32 	// This never occurs for generated message types.
       
    33 	// It implies that a hand-crafted type has missing Go fields
       
    34 	// for specific protobuf message fields.
       
    35 	return fieldInfo{
       
    36 		fieldDesc: fd,
       
    37 		has: func(p pointer) bool {
       
    38 			return false
       
    39 		},
       
    40 		clear: func(p pointer) {
       
    41 			panic("missing Go struct field for " + string(fd.FullName()))
       
    42 		},
       
    43 		get: func(p pointer) pref.Value {
       
    44 			return fd.Default()
       
    45 		},
       
    46 		set: func(p pointer, v pref.Value) {
       
    47 			panic("missing Go struct field for " + string(fd.FullName()))
       
    48 		},
       
    49 		mutable: func(p pointer) pref.Value {
       
    50 			panic("missing Go struct field for " + string(fd.FullName()))
       
    51 		},
       
    52 		newMessage: func() pref.Message {
       
    53 			panic("missing Go struct field for " + string(fd.FullName()))
       
    54 		},
       
    55 		newField: func() pref.Value {
       
    56 			if v := fd.Default(); v.IsValid() {
       
    57 				return v
       
    58 			}
       
    59 			panic("missing Go struct field for " + string(fd.FullName()))
       
    60 		},
       
    61 	}
       
    62 }
       
    63 
       
    64 func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo {
       
    65 	ft := fs.Type
       
    66 	if ft.Kind() != reflect.Interface {
       
    67 		panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", fd.FullName(), ft))
       
    68 	}
       
    69 	if ot.Kind() != reflect.Struct {
       
    70 		panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", fd.FullName(), ot))
       
    71 	}
       
    72 	if !reflect.PtrTo(ot).Implements(ft) {
       
    73 		panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", fd.FullName(), ot, ft))
       
    74 	}
       
    75 	conv := NewConverter(ot.Field(0).Type, fd)
       
    76 	isMessage := fd.Message() != nil
       
    77 
       
    78 	// TODO: Implement unsafe fast path?
       
    79 	fieldOffset := offsetOf(fs, x)
       
    80 	return fieldInfo{
       
    81 		// NOTE: The logic below intentionally assumes that oneof fields are
       
    82 		// well-formatted. That is, the oneof interface never contains a
       
    83 		// typed nil pointer to one of the wrapper structs.
       
    84 
       
    85 		fieldDesc: fd,
       
    86 		has: func(p pointer) bool {
       
    87 			if p.IsNil() {
       
    88 				return false
       
    89 			}
       
    90 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
    91 			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
       
    92 				return false
       
    93 			}
       
    94 			return true
       
    95 		},
       
    96 		clear: func(p pointer) {
       
    97 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
    98 			if rv.IsNil() || rv.Elem().Type().Elem() != ot {
       
    99 				// NOTE: We intentionally don't check for rv.Elem().IsNil()
       
   100 				// so that (*OneofWrapperType)(nil) gets cleared to nil.
       
   101 				return
       
   102 			}
       
   103 			rv.Set(reflect.Zero(rv.Type()))
       
   104 		},
       
   105 		get: func(p pointer) pref.Value {
       
   106 			if p.IsNil() {
       
   107 				return conv.Zero()
       
   108 			}
       
   109 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   110 			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
       
   111 				return conv.Zero()
       
   112 			}
       
   113 			rv = rv.Elem().Elem().Field(0)
       
   114 			return conv.PBValueOf(rv)
       
   115 		},
       
   116 		set: func(p pointer, v pref.Value) {
       
   117 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   118 			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
       
   119 				rv.Set(reflect.New(ot))
       
   120 			}
       
   121 			rv = rv.Elem().Elem().Field(0)
       
   122 			rv.Set(conv.GoValueOf(v))
       
   123 		},
       
   124 		mutable: func(p pointer) pref.Value {
       
   125 			if !isMessage {
       
   126 				panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", fd.FullName()))
       
   127 			}
       
   128 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   129 			if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
       
   130 				rv.Set(reflect.New(ot))
       
   131 			}
       
   132 			rv = rv.Elem().Elem().Field(0)
       
   133 			if rv.Kind() == reflect.Ptr && rv.IsNil() {
       
   134 				rv.Set(conv.GoValueOf(pref.ValueOfMessage(conv.New().Message())))
       
   135 			}
       
   136 			return conv.PBValueOf(rv)
       
   137 		},
       
   138 		newMessage: func() pref.Message {
       
   139 			return conv.New().Message()
       
   140 		},
       
   141 		newField: func() pref.Value {
       
   142 			return conv.New()
       
   143 		},
       
   144 	}
       
   145 }
       
   146 
       
   147 func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
       
   148 	ft := fs.Type
       
   149 	if ft.Kind() != reflect.Map {
       
   150 		panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", fd.FullName(), ft))
       
   151 	}
       
   152 	conv := NewConverter(ft, fd)
       
   153 
       
   154 	// TODO: Implement unsafe fast path?
       
   155 	fieldOffset := offsetOf(fs, x)
       
   156 	return fieldInfo{
       
   157 		fieldDesc: fd,
       
   158 		has: func(p pointer) bool {
       
   159 			if p.IsNil() {
       
   160 				return false
       
   161 			}
       
   162 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   163 			return rv.Len() > 0
       
   164 		},
       
   165 		clear: func(p pointer) {
       
   166 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   167 			rv.Set(reflect.Zero(rv.Type()))
       
   168 		},
       
   169 		get: func(p pointer) pref.Value {
       
   170 			if p.IsNil() {
       
   171 				return conv.Zero()
       
   172 			}
       
   173 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   174 			if rv.Len() == 0 {
       
   175 				return conv.Zero()
       
   176 			}
       
   177 			return conv.PBValueOf(rv)
       
   178 		},
       
   179 		set: func(p pointer, v pref.Value) {
       
   180 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   181 			pv := conv.GoValueOf(v)
       
   182 			if pv.IsNil() {
       
   183 				panic(fmt.Sprintf("map field %v cannot be set with read-only value", fd.FullName()))
       
   184 			}
       
   185 			rv.Set(pv)
       
   186 		},
       
   187 		mutable: func(p pointer) pref.Value {
       
   188 			v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   189 			if v.IsNil() {
       
   190 				v.Set(reflect.MakeMap(fs.Type))
       
   191 			}
       
   192 			return conv.PBValueOf(v)
       
   193 		},
       
   194 		newField: func() pref.Value {
       
   195 			return conv.New()
       
   196 		},
       
   197 	}
       
   198 }
       
   199 
       
   200 func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
       
   201 	ft := fs.Type
       
   202 	if ft.Kind() != reflect.Slice {
       
   203 		panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", fd.FullName(), ft))
       
   204 	}
       
   205 	conv := NewConverter(reflect.PtrTo(ft), fd)
       
   206 
       
   207 	// TODO: Implement unsafe fast path?
       
   208 	fieldOffset := offsetOf(fs, x)
       
   209 	return fieldInfo{
       
   210 		fieldDesc: fd,
       
   211 		has: func(p pointer) bool {
       
   212 			if p.IsNil() {
       
   213 				return false
       
   214 			}
       
   215 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   216 			return rv.Len() > 0
       
   217 		},
       
   218 		clear: func(p pointer) {
       
   219 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   220 			rv.Set(reflect.Zero(rv.Type()))
       
   221 		},
       
   222 		get: func(p pointer) pref.Value {
       
   223 			if p.IsNil() {
       
   224 				return conv.Zero()
       
   225 			}
       
   226 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type)
       
   227 			if rv.Elem().Len() == 0 {
       
   228 				return conv.Zero()
       
   229 			}
       
   230 			return conv.PBValueOf(rv)
       
   231 		},
       
   232 		set: func(p pointer, v pref.Value) {
       
   233 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   234 			pv := conv.GoValueOf(v)
       
   235 			if pv.IsNil() {
       
   236 				panic(fmt.Sprintf("list field %v cannot be set with read-only value", fd.FullName()))
       
   237 			}
       
   238 			rv.Set(pv.Elem())
       
   239 		},
       
   240 		mutable: func(p pointer) pref.Value {
       
   241 			v := p.Apply(fieldOffset).AsValueOf(fs.Type)
       
   242 			return conv.PBValueOf(v)
       
   243 		},
       
   244 		newField: func() pref.Value {
       
   245 			return conv.New()
       
   246 		},
       
   247 	}
       
   248 }
       
   249 
       
   250 var (
       
   251 	nilBytes   = reflect.ValueOf([]byte(nil))
       
   252 	emptyBytes = reflect.ValueOf([]byte{})
       
   253 )
       
   254 
       
   255 func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
       
   256 	ft := fs.Type
       
   257 	nullable := fd.HasPresence()
       
   258 	isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8
       
   259 	if nullable {
       
   260 		if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
       
   261 			// This never occurs for generated message types.
       
   262 			// Despite the protobuf type system specifying presence,
       
   263 			// the Go field type cannot represent it.
       
   264 			nullable = false
       
   265 		}
       
   266 		if ft.Kind() == reflect.Ptr {
       
   267 			ft = ft.Elem()
       
   268 		}
       
   269 	}
       
   270 	conv := NewConverter(ft, fd)
       
   271 
       
   272 	// TODO: Implement unsafe fast path?
       
   273 	fieldOffset := offsetOf(fs, x)
       
   274 	return fieldInfo{
       
   275 		fieldDesc: fd,
       
   276 		has: func(p pointer) bool {
       
   277 			if p.IsNil() {
       
   278 				return false
       
   279 			}
       
   280 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   281 			if nullable {
       
   282 				return !rv.IsNil()
       
   283 			}
       
   284 			switch rv.Kind() {
       
   285 			case reflect.Bool:
       
   286 				return rv.Bool()
       
   287 			case reflect.Int32, reflect.Int64:
       
   288 				return rv.Int() != 0
       
   289 			case reflect.Uint32, reflect.Uint64:
       
   290 				return rv.Uint() != 0
       
   291 			case reflect.Float32, reflect.Float64:
       
   292 				return rv.Float() != 0 || math.Signbit(rv.Float())
       
   293 			case reflect.String, reflect.Slice:
       
   294 				return rv.Len() > 0
       
   295 			default:
       
   296 				panic(fmt.Sprintf("field %v has invalid type: %v", fd.FullName(), rv.Type())) // should never happen
       
   297 			}
       
   298 		},
       
   299 		clear: func(p pointer) {
       
   300 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   301 			rv.Set(reflect.Zero(rv.Type()))
       
   302 		},
       
   303 		get: func(p pointer) pref.Value {
       
   304 			if p.IsNil() {
       
   305 				return conv.Zero()
       
   306 			}
       
   307 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   308 			if nullable {
       
   309 				if rv.IsNil() {
       
   310 					return conv.Zero()
       
   311 				}
       
   312 				if rv.Kind() == reflect.Ptr {
       
   313 					rv = rv.Elem()
       
   314 				}
       
   315 			}
       
   316 			return conv.PBValueOf(rv)
       
   317 		},
       
   318 		set: func(p pointer, v pref.Value) {
       
   319 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   320 			if nullable && rv.Kind() == reflect.Ptr {
       
   321 				if rv.IsNil() {
       
   322 					rv.Set(reflect.New(ft))
       
   323 				}
       
   324 				rv = rv.Elem()
       
   325 			}
       
   326 			rv.Set(conv.GoValueOf(v))
       
   327 			if isBytes && rv.Len() == 0 {
       
   328 				if nullable {
       
   329 					rv.Set(emptyBytes) // preserve presence
       
   330 				} else {
       
   331 					rv.Set(nilBytes) // do not preserve presence
       
   332 				}
       
   333 			}
       
   334 		},
       
   335 		newField: func() pref.Value {
       
   336 			return conv.New()
       
   337 		},
       
   338 	}
       
   339 }
       
   340 
       
   341 func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldInfo {
       
   342 	if !flags.ProtoLegacy {
       
   343 		panic("no support for proto1 weak fields")
       
   344 	}
       
   345 
       
   346 	var once sync.Once
       
   347 	var messageType pref.MessageType
       
   348 	lazyInit := func() {
       
   349 		once.Do(func() {
       
   350 			messageName := fd.Message().FullName()
       
   351 			messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
       
   352 			if messageType == nil {
       
   353 				panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName()))
       
   354 			}
       
   355 		})
       
   356 	}
       
   357 
       
   358 	num := fd.Number()
       
   359 	return fieldInfo{
       
   360 		fieldDesc: fd,
       
   361 		has: func(p pointer) bool {
       
   362 			if p.IsNil() {
       
   363 				return false
       
   364 			}
       
   365 			_, ok := p.Apply(weakOffset).WeakFields().get(num)
       
   366 			return ok
       
   367 		},
       
   368 		clear: func(p pointer) {
       
   369 			p.Apply(weakOffset).WeakFields().clear(num)
       
   370 		},
       
   371 		get: func(p pointer) pref.Value {
       
   372 			lazyInit()
       
   373 			if p.IsNil() {
       
   374 				return pref.ValueOfMessage(messageType.Zero())
       
   375 			}
       
   376 			m, ok := p.Apply(weakOffset).WeakFields().get(num)
       
   377 			if !ok {
       
   378 				return pref.ValueOfMessage(messageType.Zero())
       
   379 			}
       
   380 			return pref.ValueOfMessage(m.ProtoReflect())
       
   381 		},
       
   382 		set: func(p pointer, v pref.Value) {
       
   383 			lazyInit()
       
   384 			m := v.Message()
       
   385 			if m.Descriptor() != messageType.Descriptor() {
       
   386 				if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want {
       
   387 					panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want))
       
   388 				}
       
   389 				panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName()))
       
   390 			}
       
   391 			p.Apply(weakOffset).WeakFields().set(num, m.Interface())
       
   392 		},
       
   393 		mutable: func(p pointer) pref.Value {
       
   394 			lazyInit()
       
   395 			fs := p.Apply(weakOffset).WeakFields()
       
   396 			m, ok := fs.get(num)
       
   397 			if !ok {
       
   398 				m = messageType.New().Interface()
       
   399 				fs.set(num, m)
       
   400 			}
       
   401 			return pref.ValueOfMessage(m.ProtoReflect())
       
   402 		},
       
   403 		newMessage: func() pref.Message {
       
   404 			lazyInit()
       
   405 			return messageType.New()
       
   406 		},
       
   407 		newField: func() pref.Value {
       
   408 			lazyInit()
       
   409 			return pref.ValueOfMessage(messageType.New())
       
   410 		},
       
   411 	}
       
   412 }
       
   413 
       
   414 func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
       
   415 	ft := fs.Type
       
   416 	conv := NewConverter(ft, fd)
       
   417 
       
   418 	// TODO: Implement unsafe fast path?
       
   419 	fieldOffset := offsetOf(fs, x)
       
   420 	return fieldInfo{
       
   421 		fieldDesc: fd,
       
   422 		has: func(p pointer) bool {
       
   423 			if p.IsNil() {
       
   424 				return false
       
   425 			}
       
   426 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   427 			if fs.Type.Kind() != reflect.Ptr {
       
   428 				return !isZero(rv)
       
   429 			}
       
   430 			return !rv.IsNil()
       
   431 		},
       
   432 		clear: func(p pointer) {
       
   433 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   434 			rv.Set(reflect.Zero(rv.Type()))
       
   435 		},
       
   436 		get: func(p pointer) pref.Value {
       
   437 			if p.IsNil() {
       
   438 				return conv.Zero()
       
   439 			}
       
   440 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   441 			return conv.PBValueOf(rv)
       
   442 		},
       
   443 		set: func(p pointer, v pref.Value) {
       
   444 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   445 			rv.Set(conv.GoValueOf(v))
       
   446 			if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
       
   447 				panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName()))
       
   448 			}
       
   449 		},
       
   450 		mutable: func(p pointer) pref.Value {
       
   451 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   452 			if fs.Type.Kind() == reflect.Ptr && rv.IsNil() {
       
   453 				rv.Set(conv.GoValueOf(conv.New()))
       
   454 			}
       
   455 			return conv.PBValueOf(rv)
       
   456 		},
       
   457 		newMessage: func() pref.Message {
       
   458 			return conv.New().Message()
       
   459 		},
       
   460 		newField: func() pref.Value {
       
   461 			return conv.New()
       
   462 		},
       
   463 	}
       
   464 }
       
   465 
       
   466 type oneofInfo struct {
       
   467 	oneofDesc pref.OneofDescriptor
       
   468 	which     func(pointer) pref.FieldNumber
       
   469 }
       
   470 
       
   471 func makeOneofInfo(od pref.OneofDescriptor, si structInfo, x exporter) *oneofInfo {
       
   472 	oi := &oneofInfo{oneofDesc: od}
       
   473 	if od.IsSynthetic() {
       
   474 		fs := si.fieldsByNumber[od.Fields().Get(0).Number()]
       
   475 		fieldOffset := offsetOf(fs, x)
       
   476 		oi.which = func(p pointer) pref.FieldNumber {
       
   477 			if p.IsNil() {
       
   478 				return 0
       
   479 			}
       
   480 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   481 			if rv.IsNil() { // valid on either *T or []byte
       
   482 				return 0
       
   483 			}
       
   484 			return od.Fields().Get(0).Number()
       
   485 		}
       
   486 	} else {
       
   487 		fs := si.oneofsByName[od.Name()]
       
   488 		fieldOffset := offsetOf(fs, x)
       
   489 		oi.which = func(p pointer) pref.FieldNumber {
       
   490 			if p.IsNil() {
       
   491 				return 0
       
   492 			}
       
   493 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
       
   494 			if rv.IsNil() {
       
   495 				return 0
       
   496 			}
       
   497 			rv = rv.Elem()
       
   498 			if rv.IsNil() {
       
   499 				return 0
       
   500 			}
       
   501 			return si.oneofWrappersByType[rv.Type().Elem()]
       
   502 		}
       
   503 	}
       
   504 	return oi
       
   505 }
       
   506 
       
   507 // isZero is identical to reflect.Value.IsZero.
       
   508 // TODO: Remove this when Go1.13 is the minimally supported Go version.
       
   509 func isZero(v reflect.Value) bool {
       
   510 	switch v.Kind() {
       
   511 	case reflect.Bool:
       
   512 		return !v.Bool()
       
   513 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       
   514 		return v.Int() == 0
       
   515 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
       
   516 		return v.Uint() == 0
       
   517 	case reflect.Float32, reflect.Float64:
       
   518 		return math.Float64bits(v.Float()) == 0
       
   519 	case reflect.Complex64, reflect.Complex128:
       
   520 		c := v.Complex()
       
   521 		return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
       
   522 	case reflect.Array:
       
   523 		for i := 0; i < v.Len(); i++ {
       
   524 			if !isZero(v.Index(i)) {
       
   525 				return false
       
   526 			}
       
   527 		}
       
   528 		return true
       
   529 	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
       
   530 		return v.IsNil()
       
   531 	case reflect.String:
       
   532 		return v.Len() == 0
       
   533 	case reflect.Struct:
       
   534 		for i := 0; i < v.NumField(); i++ {
       
   535 			if !isZero(v.Field(i)) {
       
   536 				return false
       
   537 			}
       
   538 		}
       
   539 		return true
       
   540 	default:
       
   541 		panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()})
       
   542 	}
       
   543 }