github.com/whiteCcinn/protobuf-go@v1.0.9/internal/impl/convert_list.go (about) 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 "github.com/whiteCcinn/protobuf-go/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() interface{} { 140 return ls.v.Interface() 141 }