// 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 (
	
	

	
)

func ( reflect.Type,  protoreflect.FieldDescriptor) Converter {
	switch {
	case .Kind() == reflect.Ptr && .Elem().Kind() == reflect.Slice:
		return &listPtrConverter{, newSingularConverter(.Elem().Elem(), )}
	case .Kind() == reflect.Slice:
		return &listConverter{, newSingularConverter(.Elem(), )}
	}
	panic(fmt.Sprintf("invalid Go type %v for field %v", , .FullName()))
}

type listConverter struct {
	goType reflect.Type // []T
	c      Converter
}

func ( *listConverter) ( reflect.Value) protoreflect.Value {
	if .Type() != .goType {
		panic(fmt.Sprintf("invalid type: got %v, want %v", .Type(), .goType))
	}
	 := reflect.New(.goType)
	.Elem().Set()
	return protoreflect.ValueOfList(&listReflect{, .c})
}

func ( *listConverter) ( protoreflect.Value) reflect.Value {
	 := .List().(*listReflect).v
	if .IsNil() {
		return reflect.Zero(.goType)
	}
	return .Elem()
}

func ( *listConverter) ( protoreflect.Value) bool {
	,  := .Interface().(*listReflect)
	if ! {
		return false
	}
	return .v.Type().Elem() == .goType
}

func ( *listConverter) ( reflect.Value) bool {
	return .IsValid() && .Type() == .goType
}

func ( *listConverter) () protoreflect.Value {
	return protoreflect.ValueOfList(&listReflect{reflect.New(.goType), .c})
}

func ( *listConverter) () protoreflect.Value {
	return protoreflect.ValueOfList(&listReflect{reflect.Zero(reflect.PtrTo(.goType)), .c})
}

type listPtrConverter struct {
	goType reflect.Type // *[]T
	c      Converter
}

func ( *listPtrConverter) ( reflect.Value) protoreflect.Value {
	if .Type() != .goType {
		panic(fmt.Sprintf("invalid type: got %v, want %v", .Type(), .goType))
	}
	return protoreflect.ValueOfList(&listReflect{, .c})
}

func ( *listPtrConverter) ( protoreflect.Value) reflect.Value {
	return .List().(*listReflect).v
}

func ( *listPtrConverter) ( protoreflect.Value) bool {
	,  := .Interface().(*listReflect)
	if ! {
		return false
	}
	return .v.Type() == .goType
}

func ( *listPtrConverter) ( reflect.Value) bool {
	return .IsValid() && .Type() == .goType
}

func ( *listPtrConverter) () protoreflect.Value {
	return .PBValueOf(reflect.New(.goType.Elem()))
}

func ( *listPtrConverter) () protoreflect.Value {
	return .PBValueOf(reflect.Zero(.goType))
}

type listReflect struct {
	v    reflect.Value // *[]T
	conv Converter
}

func ( *listReflect) () int {
	if .v.IsNil() {
		return 0
	}
	return .v.Elem().Len()
}
func ( *listReflect) ( int) protoreflect.Value {
	return .conv.PBValueOf(.v.Elem().Index())
}
func ( *listReflect) ( int,  protoreflect.Value) {
	.v.Elem().Index().Set(.conv.GoValueOf())
}
func ( *listReflect) ( protoreflect.Value) {
	.v.Elem().Set(reflect.Append(.v.Elem(), .conv.GoValueOf()))
}
func ( *listReflect) () protoreflect.Value {
	if ,  := .conv.(*messageConverter); ! {
		panic("invalid AppendMutable on list with non-message type")
	}
	 := .NewElement()
	.Append()
	return 
}
func ( *listReflect) ( int) {
	.v.Elem().Set(.v.Elem().Slice(0, ))
}
func ( *listReflect) () protoreflect.Value {
	return .conv.New()
}
func ( *listReflect) () bool {
	return !.v.IsNil()
}
func ( *listReflect) () interface{} {
	return .v.Interface()
}