21 validation validationInfo |
21 validation validationInfo |
22 } |
22 } |
23 |
23 |
24 var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo |
24 var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo |
25 |
25 |
26 func getExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { |
26 func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { |
27 if xi, ok := xt.(*ExtensionInfo); ok { |
27 if xi, ok := xt.(*ExtensionInfo); ok { |
28 xi.lazyInit() |
28 xi.lazyInit() |
29 return xi.info |
29 return xi.info |
30 } |
30 } |
31 return legacyLoadExtensionFieldInfo(xt) |
31 return legacyLoadExtensionFieldInfo(xt) |
32 } |
32 } |
33 |
33 |
34 // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. |
34 // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. |
35 func legacyLoadExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { |
35 func legacyLoadExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { |
36 if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { |
36 if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { |
37 return xi.(*extensionFieldInfo) |
37 return xi.(*extensionFieldInfo) |
38 } |
38 } |
39 e := makeExtensionFieldInfo(xt.TypeDescriptor()) |
39 e := makeExtensionFieldInfo(xt.TypeDescriptor()) |
40 if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok { |
40 if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok { |
41 return e.(*extensionFieldInfo) |
41 return e.(*extensionFieldInfo) |
42 } |
42 } |
43 return e |
43 return e |
44 } |
44 } |
45 |
45 |
46 func makeExtensionFieldInfo(xd pref.ExtensionDescriptor) *extensionFieldInfo { |
46 func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo { |
47 var wiretag uint64 |
47 var wiretag uint64 |
48 if !xd.IsPacked() { |
48 if !xd.IsPacked() { |
49 wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()]) |
49 wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()]) |
50 } else { |
50 } else { |
51 wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType) |
51 wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType) |
57 } |
57 } |
58 // Does the unmarshal function need a value passed to it? |
58 // Does the unmarshal function need a value passed to it? |
59 // This is true for composite types, where we pass in a message, list, or map to fill in, |
59 // This is true for composite types, where we pass in a message, list, or map to fill in, |
60 // and for enums, where we pass in a prototype value to specify the concrete enum type. |
60 // and for enums, where we pass in a prototype value to specify the concrete enum type. |
61 switch xd.Kind() { |
61 switch xd.Kind() { |
62 case pref.MessageKind, pref.GroupKind, pref.EnumKind: |
62 case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.EnumKind: |
63 e.unmarshalNeedsValue = true |
63 e.unmarshalNeedsValue = true |
64 default: |
64 default: |
65 if xd.Cardinality() == pref.Repeated { |
65 if xd.Cardinality() == protoreflect.Repeated { |
66 e.unmarshalNeedsValue = true |
66 e.unmarshalNeedsValue = true |
67 } |
67 } |
68 } |
68 } |
69 return e |
69 return e |
70 } |
70 } |
71 |
71 |
72 type lazyExtensionValue struct { |
72 type lazyExtensionValue struct { |
73 atomicOnce uint32 // atomically set if value is valid |
73 atomicOnce uint32 // atomically set if value is valid |
74 mu sync.Mutex |
74 mu sync.Mutex |
75 xi *extensionFieldInfo |
75 xi *extensionFieldInfo |
76 value pref.Value |
76 value protoreflect.Value |
77 b []byte |
77 b []byte |
78 fn func() pref.Value |
78 fn func() protoreflect.Value |
79 } |
79 } |
80 |
80 |
81 type ExtensionField struct { |
81 type ExtensionField struct { |
82 typ pref.ExtensionType |
82 typ protoreflect.ExtensionType |
83 |
83 |
84 // value is either the value of GetValue, |
84 // value is either the value of GetValue, |
85 // or a *lazyExtensionValue that then returns the value of GetValue. |
85 // or a *lazyExtensionValue that then returns the value of GetValue. |
86 value pref.Value |
86 value protoreflect.Value |
87 lazy *lazyExtensionValue |
87 lazy *lazyExtensionValue |
88 } |
88 } |
89 |
89 |
90 func (f *ExtensionField) appendLazyBytes(xt pref.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) { |
90 func (f *ExtensionField) appendLazyBytes(xt protoreflect.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) { |
91 if f.lazy == nil { |
91 if f.lazy == nil { |
92 f.lazy = &lazyExtensionValue{xi: xi} |
92 f.lazy = &lazyExtensionValue{xi: xi} |
93 } |
93 } |
94 f.typ = xt |
94 f.typ = xt |
95 f.lazy.xi = xi |
95 f.lazy.xi = xi |
96 f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp) |
96 f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp) |
97 f.lazy.b = append(f.lazy.b, b...) |
97 f.lazy.b = append(f.lazy.b, b...) |
98 } |
98 } |
99 |
99 |
100 func (f *ExtensionField) canLazy(xt pref.ExtensionType) bool { |
100 func (f *ExtensionField) canLazy(xt protoreflect.ExtensionType) bool { |
101 if f.typ == nil { |
101 if f.typ == nil { |
102 return true |
102 return true |
103 } |
103 } |
104 if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { |
104 if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { |
105 return true |
105 return true |
152 atomic.StoreUint32(&f.lazy.atomicOnce, 1) |
152 atomic.StoreUint32(&f.lazy.atomicOnce, 1) |
153 } |
153 } |
154 |
154 |
155 // Set sets the type and value of the extension field. |
155 // Set sets the type and value of the extension field. |
156 // This must not be called concurrently. |
156 // This must not be called concurrently. |
157 func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) { |
157 func (f *ExtensionField) Set(t protoreflect.ExtensionType, v protoreflect.Value) { |
158 f.typ = t |
158 f.typ = t |
159 f.value = v |
159 f.value = v |
160 f.lazy = nil |
160 f.lazy = nil |
161 } |
161 } |
162 |
162 |
163 // SetLazy sets the type and a value that is to be lazily evaluated upon first use. |
163 // SetLazy sets the type and a value that is to be lazily evaluated upon first use. |
164 // This must not be called concurrently. |
164 // This must not be called concurrently. |
165 func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) { |
165 func (f *ExtensionField) SetLazy(t protoreflect.ExtensionType, fn func() protoreflect.Value) { |
166 f.typ = t |
166 f.typ = t |
167 f.lazy = &lazyExtensionValue{fn: fn} |
167 f.lazy = &lazyExtensionValue{fn: fn} |
168 } |
168 } |
169 |
169 |
170 // Value returns the value of the extension field. |
170 // Value returns the value of the extension field. |
171 // This may be called concurrently. |
171 // This may be called concurrently. |
172 func (f *ExtensionField) Value() pref.Value { |
172 func (f *ExtensionField) Value() protoreflect.Value { |
173 if f.lazy != nil { |
173 if f.lazy != nil { |
174 if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { |
174 if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { |
175 f.lazyInit() |
175 f.lazyInit() |
176 } |
176 } |
177 return f.lazy.value |
177 return f.lazy.value |