Copyright 2018 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package impl

import (
	
	
	
	

	
	pref 
	preg 
)

type fieldInfo struct {
	fieldDesc pref.FieldDescriptor
These fields are used for protobuf reflection support.
	has        func(pointer) bool
	clear      func(pointer)
	get        func(pointer) pref.Value
	set        func(pointer, pref.Value)
	mutable    func(pointer) pref.Value
	newMessage func() pref.Message
	newField   func() pref.Value
}

func ( pref.FieldDescriptor,  reflect.StructField,  exporter,  reflect.Type) fieldInfo {
	 := .Type
	if .Kind() != reflect.Interface {
		panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", .FullName(), ))
	}
	if .Kind() != reflect.Struct {
		panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", .FullName(), ))
	}
	if !reflect.PtrTo().Implements() {
		panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", .FullName(), , ))
	}
	 := NewConverter(.Field(0).Type, )
	 := .Message() != nil
TODO: Implement unsafe fast path?
	 := offsetOf(, )
NOTE: The logic below intentionally assumes that oneof fields are well-formatted. That is, the oneof interface never contains a typed nil pointer to one of the wrapper structs.

		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() || .Elem().Type().Elem() !=  || .Elem().IsNil() {
				return false
			}
			return true
		},
		clear: func( pointer) {
			 := .Apply().AsValueOf(.Type).Elem()
NOTE: We intentionally don't check for rv.Elem().IsNil() so that (*OneofWrapperType)(nil) gets cleared to nil.
				return
			}
			.Set(reflect.Zero(.Type()))
		},
		get: func( pointer) pref.Value {
			if .IsNil() {
				return .Zero()
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() || .Elem().Type().Elem() !=  || .Elem().IsNil() {
				return .Zero()
			}
			 = .Elem().Elem().Field(0)
			return .PBValueOf()
		},
		set: func( pointer,  pref.Value) {
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() || .Elem().Type().Elem() !=  || .Elem().IsNil() {
				.Set(reflect.New())
			}
			 = .Elem().Elem().Field(0)
			.Set(.GoValueOf())
		},
		mutable: func( pointer) pref.Value {
			if ! {
				panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", .FullName()))
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() || .Elem().Type().Elem() !=  || .Elem().IsNil() {
				.Set(reflect.New())
			}
			 = .Elem().Elem().Field(0)
			if .IsNil() {
				.Set(.GoValueOf(pref.ValueOfMessage(.New().Message())))
			}
			return .PBValueOf()
		},
		newMessage: func() pref.Message {
			return .New().Message()
		},
		newField: func() pref.Value {
			return .New()
		},
	}
}

func ( pref.FieldDescriptor,  reflect.StructField,  exporter) fieldInfo {
	 := .Type
	if .Kind() != reflect.Map {
		panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", .FullName(), ))
	}
	 := NewConverter(, )
TODO: Implement unsafe fast path?
	 := offsetOf(, )
	return fieldInfo{
		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			 := .Apply().AsValueOf(.Type).Elem()
			return .Len() > 0
		},
		clear: func( pointer) {
			 := .Apply().AsValueOf(.Type).Elem()
			.Set(reflect.Zero(.Type()))
		},
		get: func( pointer) pref.Value {
			if .IsNil() {
				return .Zero()
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .Len() == 0 {
				return .Zero()
			}
			return .PBValueOf()
		},
		set: func( pointer,  pref.Value) {
			 := .Apply().AsValueOf(.Type).Elem()
			 := .GoValueOf()
			if .IsNil() {
				panic(fmt.Sprintf("map field %v cannot be set with read-only value", .FullName()))
			}
			.Set()
		},
		mutable: func( pointer) pref.Value {
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() {
				.Set(reflect.MakeMap(.Type))
			}
			return .PBValueOf()
		},
		newField: func() pref.Value {
			return .New()
		},
	}
}

func ( pref.FieldDescriptor,  reflect.StructField,  exporter) fieldInfo {
	 := .Type
	if .Kind() != reflect.Slice {
		panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", .FullName(), ))
	}
	 := NewConverter(reflect.PtrTo(), )
TODO: Implement unsafe fast path?
	 := offsetOf(, )
	return fieldInfo{
		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			 := .Apply().AsValueOf(.Type).Elem()
			return .Len() > 0
		},
		clear: func( pointer) {
			 := .Apply().AsValueOf(.Type).Elem()
			.Set(reflect.Zero(.Type()))
		},
		get: func( pointer) pref.Value {
			if .IsNil() {
				return .Zero()
			}
			 := .Apply().AsValueOf(.Type)
			if .Elem().Len() == 0 {
				return .Zero()
			}
			return .PBValueOf()
		},
		set: func( pointer,  pref.Value) {
			 := .Apply().AsValueOf(.Type).Elem()
			 := .GoValueOf()
			if .IsNil() {
				panic(fmt.Sprintf("list field %v cannot be set with read-only value", .FullName()))
			}
			.Set(.Elem())
		},
		mutable: func( pointer) pref.Value {
			 := .Apply().AsValueOf(.Type)
			return .PBValueOf()
		},
		newField: func() pref.Value {
			return .New()
		},
	}
}

var (
	nilBytes   = reflect.ValueOf([]byte(nil))
	emptyBytes = reflect.ValueOf([]byte{})
)

func ( pref.FieldDescriptor,  reflect.StructField,  exporter) fieldInfo {
	 := .Type
	 := .HasPresence()
	 := .Kind() == reflect.Slice && .Elem().Kind() == reflect.Uint8
	if  {
		if .Kind() != reflect.Ptr && .Kind() != reflect.Slice {
			panic(fmt.Sprintf("field %v has invalid type: got %v, want pointer", .FullName(), ))
		}
		if .Kind() == reflect.Ptr {
			 = .Elem()
		}
	}
	 := NewConverter(, )
TODO: Implement unsafe fast path?
	 := offsetOf(, )
	return fieldInfo{
		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if  {
				return !.IsNil()
			}
			switch .Kind() {
			case reflect.Bool:
				return .Bool()
			case reflect.Int32, reflect.Int64:
				return .Int() != 0
			case reflect.Uint32, reflect.Uint64:
				return .Uint() != 0
			case reflect.Float32, reflect.Float64:
				return .Float() != 0 || math.Signbit(.Float())
			case reflect.String, reflect.Slice:
				return .Len() > 0
			default:
				panic(fmt.Sprintf("field %v has invalid type: %v", .FullName(), .Type())) // should never happen
			}
		},
		clear: func( pointer) {
			 := .Apply().AsValueOf(.Type).Elem()
			.Set(reflect.Zero(.Type()))
		},
		get: func( pointer) pref.Value {
			if .IsNil() {
				return .Zero()
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if  {
				if .IsNil() {
					return .Zero()
				}
				if .Kind() == reflect.Ptr {
					 = .Elem()
				}
			}
			return .PBValueOf()
		},
		set: func( pointer,  pref.Value) {
			 := .Apply().AsValueOf(.Type).Elem()
			if  && .Kind() == reflect.Ptr {
				if .IsNil() {
					.Set(reflect.New())
				}
				 = .Elem()
			}
			.Set(.GoValueOf())
			if  && .Len() == 0 {
				if  {
					.Set(emptyBytes) // preserve presence
				} else {
					.Set(nilBytes) // do not preserve presence
				}
			}
		},
		newField: func() pref.Value {
			return .New()
		},
	}
}

func ( pref.FieldDescriptor,  offset) fieldInfo {
	if !flags.ProtoLegacy {
		panic("no support for proto1 weak fields")
	}

	var  sync.Once
	var  pref.MessageType
	 := func() {
		.Do(func() {
			 := .Message().FullName()
			, _ = preg.GlobalTypes.FindMessageByName()
			if  == nil {
				panic(fmt.Sprintf("weak message %v for field %v is not linked in", , .FullName()))
			}
		})
	}

	 := .Number()
	return fieldInfo{
		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			,  := .Apply().WeakFields().get()
			return 
		},
		clear: func( pointer) {
			.Apply().WeakFields().clear()
		},
		get: func( pointer) pref.Value {
			()
			if .IsNil() {
				return pref.ValueOfMessage(.Zero())
			}
			,  := .Apply().WeakFields().get()
			if ! {
				return pref.ValueOfMessage(.Zero())
			}
			return pref.ValueOfMessage(.ProtoReflect())
		},
		set: func( pointer,  pref.Value) {
			()
			 := .Message()
			if .Descriptor() != .Descriptor() {
				if ,  := .Descriptor().FullName(), .Descriptor().FullName();  !=  {
					panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", .FullName(), , ))
				}
				panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", .FullName(), .Descriptor().FullName()))
			}
			.Apply().WeakFields().set(, .Interface())
		},
		mutable: func( pointer) pref.Value {
			()
			 := .Apply().WeakFields()
			,  := .get()
			if ! {
				 = .New().Interface()
				.set(, )
			}
			return pref.ValueOfMessage(.ProtoReflect())
		},
		newMessage: func() pref.Message {
			()
			return .New()
		},
		newField: func() pref.Value {
			()
			return pref.ValueOfMessage(.New())
		},
	}
}

func ( pref.FieldDescriptor,  reflect.StructField,  exporter) fieldInfo {
	 := .Type
	 := NewConverter(, )
TODO: Implement unsafe fast path?
	 := offsetOf(, )
	return fieldInfo{
		fieldDesc: ,
		has: func( pointer) bool {
			if .IsNil() {
				return false
			}
			 := .Apply().AsValueOf(.Type).Elem()
			return !.IsNil()
		},
		clear: func( pointer) {
			 := .Apply().AsValueOf(.Type).Elem()
			.Set(reflect.Zero(.Type()))
		},
		get: func( pointer) pref.Value {
			if .IsNil() {
				return .Zero()
			}
			 := .Apply().AsValueOf(.Type).Elem()
			return .PBValueOf()
		},
		set: func( pointer,  pref.Value) {
			 := .Apply().AsValueOf(.Type).Elem()
			.Set(.GoValueOf())
			if .IsNil() {
				panic(fmt.Sprintf("field %v has invalid nil pointer", .FullName()))
			}
		},
		mutable: func( pointer) pref.Value {
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() {
				.Set(.GoValueOf(.New()))
			}
			return .PBValueOf()
		},
		newMessage: func() pref.Message {
			return .New().Message()
		},
		newField: func() pref.Value {
			return .New()
		},
	}
}

type oneofInfo struct {
	oneofDesc pref.OneofDescriptor
	which     func(pointer) pref.FieldNumber
}

func ( pref.OneofDescriptor,  structInfo,  exporter) *oneofInfo {
	 := &oneofInfo{oneofDesc: }
	if .IsSynthetic() {
		 := .fieldsByNumber[.Fields().Get(0).Number()]
		 := offsetOf(, )
		.which = func( pointer) pref.FieldNumber {
			if .IsNil() {
				return 0
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() { // valid on either *T or []byte
				return 0
			}
			return .Fields().Get(0).Number()
		}
	} else {
		 := .oneofsByName[.Name()]
		 := offsetOf(, )
		.which = func( pointer) pref.FieldNumber {
			if .IsNil() {
				return 0
			}
			 := .Apply().AsValueOf(.Type).Elem()
			if .IsNil() {
				return 0
			}
			 = .Elem()
			if .IsNil() {
				return 0
			}
			return .oneofWrappersByType[.Type().Elem()]
		}
	}
	return