|
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 pref "google.golang.org/protobuf/reflect/protoreflect" |
|
12 ) |
|
13 |
|
14 func newListConverter(t reflect.Type, fd pref.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) pref.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 pref.ValueOfList(&listReflect{pv, c.c}) |
|
36 } |
|
37 |
|
38 func (c *listConverter) GoValueOf(v pref.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 pref.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() pref.Value { |
|
59 return pref.ValueOfList(&listReflect{reflect.New(c.goType), c.c}) |
|
60 } |
|
61 |
|
62 func (c *listConverter) Zero() pref.Value { |
|
63 return pref.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) pref.Value { |
|
72 if v.Type() != c.goType { |
|
73 panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) |
|
74 } |
|
75 return pref.ValueOfList(&listReflect{v, c.c}) |
|
76 } |
|
77 |
|
78 func (c *listPtrConverter) GoValueOf(v pref.Value) reflect.Value { |
|
79 return v.List().(*listReflect).v |
|
80 } |
|
81 |
|
82 func (c *listPtrConverter) IsValidPB(v pref.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() pref.Value { |
|
95 return c.PBValueOf(reflect.New(c.goType.Elem())) |
|
96 } |
|
97 |
|
98 func (c *listPtrConverter) Zero() pref.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) pref.Value { |
|
114 return ls.conv.PBValueOf(ls.v.Elem().Index(i)) |
|
115 } |
|
116 func (ls *listReflect) Set(i int, v pref.Value) { |
|
117 ls.v.Elem().Index(i).Set(ls.conv.GoValueOf(v)) |
|
118 } |
|
119 func (ls *listReflect) Append(v pref.Value) { |
|
120 ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(v))) |
|
121 } |
|
122 func (ls *listReflect) AppendMutable() pref.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() pref.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 } |