convert_list.go raw

   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  	"reflect"
  10  
  11  	"google.golang.org/protobuf/reflect/protoreflect"
  12  )
  13  
  14  func newListConverter(t reflect.Type, fd protoreflect.FieldDescriptor) Converter {
  15  	switch {
  16  	case t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Slice:
  17  		return &listPtrConverter{t, newSingularConverter(t.Elem().Elem(), fd)}
  18  	case t.Kind() == reflect.Slice:
  19  		return &listConverter{t, newSingularConverter(t.Elem(), fd)}
  20  	}
  21  	panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
  22  }
  23  
  24  type listConverter struct {
  25  	goType reflect.Type // []T
  26  	c      Converter
  27  }
  28  
  29  func (c *listConverter) PBValueOf(v reflect.Value) protoreflect.Value {
  30  	if v.Type() != c.goType {
  31  		panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
  32  	}
  33  	pv := reflect.New(c.goType)
  34  	pv.Elem().Set(v)
  35  	return protoreflect.ValueOfList(&listReflect{pv, c.c})
  36  }
  37  
  38  func (c *listConverter) GoValueOf(v protoreflect.Value) reflect.Value {
  39  	rv := v.List().(*listReflect).v
  40  	if rv.IsNil() {
  41  		return reflect.Zero(c.goType)
  42  	}
  43  	return rv.Elem()
  44  }
  45  
  46  func (c *listConverter) IsValidPB(v protoreflect.Value) bool {
  47  	list, ok := v.Interface().(*listReflect)
  48  	if !ok {
  49  		return false
  50  	}
  51  	return list.v.Type().Elem() == c.goType
  52  }
  53  
  54  func (c *listConverter) IsValidGo(v reflect.Value) bool {
  55  	return v.IsValid() && v.Type() == c.goType
  56  }
  57  
  58  func (c *listConverter) New() protoreflect.Value {
  59  	return protoreflect.ValueOfList(&listReflect{reflect.New(c.goType), c.c})
  60  }
  61  
  62  func (c *listConverter) Zero() protoreflect.Value {
  63  	return protoreflect.ValueOfList(&listReflect{reflect.Zero(reflect.PtrTo(c.goType)), c.c})
  64  }
  65  
  66  type listPtrConverter struct {
  67  	goType reflect.Type // *[]T
  68  	c      Converter
  69  }
  70  
  71  func (c *listPtrConverter) PBValueOf(v reflect.Value) protoreflect.Value {
  72  	if v.Type() != c.goType {
  73  		panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
  74  	}
  75  	return protoreflect.ValueOfList(&listReflect{v, c.c})
  76  }
  77  
  78  func (c *listPtrConverter) GoValueOf(v protoreflect.Value) reflect.Value {
  79  	return v.List().(*listReflect).v
  80  }
  81  
  82  func (c *listPtrConverter) IsValidPB(v protoreflect.Value) bool {
  83  	list, ok := v.Interface().(*listReflect)
  84  	if !ok {
  85  		return false
  86  	}
  87  	return list.v.Type() == c.goType
  88  }
  89  
  90  func (c *listPtrConverter) IsValidGo(v reflect.Value) bool {
  91  	return v.IsValid() && v.Type() == c.goType
  92  }
  93  
  94  func (c *listPtrConverter) New() protoreflect.Value {
  95  	return c.PBValueOf(reflect.New(c.goType.Elem()))
  96  }
  97  
  98  func (c *listPtrConverter) Zero() protoreflect.Value {
  99  	return c.PBValueOf(reflect.Zero(c.goType))
 100  }
 101  
 102  type listReflect struct {
 103  	v    reflect.Value // *[]T
 104  	conv Converter
 105  }
 106  
 107  func (ls *listReflect) Len() int {
 108  	if ls.v.IsNil() {
 109  		return 0
 110  	}
 111  	return ls.v.Elem().Len()
 112  }
 113  func (ls *listReflect) Get(i int) protoreflect.Value {
 114  	return ls.conv.PBValueOf(ls.v.Elem().Index(i))
 115  }
 116  func (ls *listReflect) Set(i int, v protoreflect.Value) {
 117  	ls.v.Elem().Index(i).Set(ls.conv.GoValueOf(v))
 118  }
 119  func (ls *listReflect) Append(v protoreflect.Value) {
 120  	ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(v)))
 121  }
 122  func (ls *listReflect) AppendMutable() protoreflect.Value {
 123  	if _, ok := ls.conv.(*messageConverter); !ok {
 124  		panic("invalid AppendMutable on list with non-message type")
 125  	}
 126  	v := ls.NewElement()
 127  	ls.Append(v)
 128  	return v
 129  }
 130  func (ls *listReflect) Truncate(i int) {
 131  	ls.v.Elem().Set(ls.v.Elem().Slice(0, i))
 132  }
 133  func (ls *listReflect) NewElement() protoreflect.Value {
 134  	return ls.conv.New()
 135  }
 136  func (ls *listReflect) IsValid() bool {
 137  	return !ls.v.IsNil()
 138  }
 139  func (ls *listReflect) protoUnwrap() any {
 140  	return ls.v.Interface()
 141  }
 142