blob: 172ce70917b8222ae9472b84a3c0871d55f3dde4 [file] [log] [blame]
Joe Tsaie2afdc22018-10-25 14:06:56 -07001// 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
5package impl
6
7import (
Joe Tsai2d5a1692018-10-29 02:10:42 -07008 "container/list"
Joe Tsaie2afdc22018-10-25 14:06:56 -07009 "reflect"
Joe Tsai95b02902018-10-31 18:23:42 -070010 "sort"
Joe Tsaie2afdc22018-10-25 14:06:56 -070011
Joe Tsaie2afdc22018-10-25 14:06:56 -070012 "github.com/golang/protobuf/v2/internal/encoding/wire"
13 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
14)
15
Joe Tsai88bc5a72018-11-05 11:42:22 -080016var bytesType = reflect.TypeOf([]byte(nil))
17
Joe Tsai95b02902018-10-31 18:23:42 -070018func makeLegacyUnknownFieldsFunc(t reflect.Type) func(p *messageDataType) pref.UnknownFields {
Joe Tsaie2afdc22018-10-25 14:06:56 -070019 fu, ok := t.FieldByName("XXX_unrecognized")
20 if !ok || fu.Type != bytesType {
21 return nil
22 }
Joe Tsaie2afdc22018-10-25 14:06:56 -070023 fieldOffset := offsetOf(fu)
Joe Tsai95b02902018-10-31 18:23:42 -070024 unkFunc := func(p *messageDataType) pref.UnknownFields {
Joe Tsaie2afdc22018-10-25 14:06:56 -070025 rv := p.p.apply(fieldOffset).asType(bytesType)
26 return (*legacyUnknownBytes)(rv.Interface().(*[]byte))
27 }
Joe Tsai95b02902018-10-31 18:23:42 -070028 extFunc := makeLegacyExtensionMapFunc(t)
29 if extFunc != nil {
30 return func(p *messageDataType) pref.UnknownFields {
31 return &legacyUnknownBytesAndExtensionMap{
32 unkFunc(p), extFunc(p), p.mi.Desc.ExtensionRanges(),
33 }
34 }
35 }
36 return unkFunc
37}
38
39// legacyUnknownBytesAndExtensionMap is a wrapper around both XXX_unrecognized
40// and also the extension field map.
41type legacyUnknownBytesAndExtensionMap struct {
42 u pref.UnknownFields
43 x legacyExtensionIface
44 r pref.FieldRanges
45}
46
47func (fs *legacyUnknownBytesAndExtensionMap) Len() int {
48 n := fs.u.Len()
49 fs.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
50 if len(x.raw) > 0 {
51 n++
52 }
53 return true
54 })
55 return n
56}
57
58func (fs *legacyUnknownBytesAndExtensionMap) Get(num pref.FieldNumber) (raw pref.RawFields) {
59 if fs.r.Has(num) {
60 return fs.x.Get(num).raw
61 }
62 return fs.u.Get(num)
63}
64
65func (fs *legacyUnknownBytesAndExtensionMap) Set(num pref.FieldNumber, raw pref.RawFields) {
66 if fs.r.Has(num) {
67 x := fs.x.Get(num)
68 x.raw = raw
69 fs.x.Set(num, x)
70 return
71 }
72 fs.u.Set(num, raw)
73}
74
75func (fs *legacyUnknownBytesAndExtensionMap) Range(f func(pref.FieldNumber, pref.RawFields) bool) {
76 // Range over unknown fields not in the extension range.
77 // Create a closure around f to capture whether iteration terminated early.
78 var stop bool
79 fs.u.Range(func(n pref.FieldNumber, b pref.RawFields) bool {
80 stop = stop || !f(n, b)
81 return !stop
82 })
83 if stop {
84 return
85 }
86
87 // Range over unknown fields in the extension range in ascending order
88 // to ensure protoreflect.UnknownFields.Range remains deterministic.
89 type entry struct {
90 num pref.FieldNumber
91 raw pref.RawFields
92 }
93 var xs []entry
94 fs.x.Range(func(n pref.FieldNumber, x legacyExtensionEntry) bool {
95 if len(x.raw) > 0 {
96 xs = append(xs, entry{n, x.raw})
97 }
98 return true
99 })
100 sort.Slice(xs, func(i, j int) bool { return xs[i].num < xs[j].num })
101 for _, x := range xs {
102 if !f(x.num, x.raw) {
103 return
104 }
105 }
106}
107
108func (fs *legacyUnknownBytesAndExtensionMap) IsSupported() bool {
109 return true
Joe Tsaie2afdc22018-10-25 14:06:56 -0700110}
111
112// legacyUnknownBytes is a wrapper around XXX_unrecognized that implements
113// the protoreflect.UnknownFields interface. This is challenging since we are
114// limited to a []byte, so we do not have much flexibility in the choice
115// of data structure that would have been ideal.
116type legacyUnknownBytes []byte
117
118func (fs *legacyUnknownBytes) Len() int {
119 // Runtime complexity: O(n)
120 b := *fs
121 m := map[pref.FieldNumber]bool{}
122 for len(b) > 0 {
123 num, _, n := wire.ConsumeField(b)
124 m[num] = true
125 b = b[n:]
126 }
127 return len(m)
128}
129
130func (fs *legacyUnknownBytes) Get(num pref.FieldNumber) (raw pref.RawFields) {
131 // Runtime complexity: O(n)
132 b := *fs
133 for len(b) > 0 {
134 num2, _, n := wire.ConsumeField(b)
135 if num == num2 {
136 raw = append(raw, b[:n]...)
137 }
138 b = b[n:]
139 }
140 return raw
141}
142
143func (fs *legacyUnknownBytes) Set(num pref.FieldNumber, raw pref.RawFields) {
144 num2, _, _ := wire.ConsumeTag(raw)
145 if len(raw) > 0 && (!raw.IsValid() || num != num2) {
146 panic("invalid raw fields")
147 }
148
149 // Remove all current fields of num.
150 // Runtime complexity: O(n)
151 b := *fs
152 out := (*fs)[:0]
153 for len(b) > 0 {
154 num2, _, n := wire.ConsumeField(b)
155 if num != num2 {
156 out = append(out, b[:n]...)
157 }
158 b = b[n:]
159 }
160 *fs = out
161
162 // Append new fields of num.
163 *fs = append(*fs, raw...)
164}
165
166func (fs *legacyUnknownBytes) Range(f func(pref.FieldNumber, pref.RawFields) bool) {
167 type entry struct {
168 num pref.FieldNumber
169 raw pref.RawFields
170 }
Joe Tsaie2afdc22018-10-25 14:06:56 -0700171
172 // Collect up a list of all the raw fields.
173 // We preserve the order such that the latest encountered fields
174 // are presented at the end.
175 //
176 // Runtime complexity: O(n)
177 b := *fs
Joe Tsai2d5a1692018-10-29 02:10:42 -0700178 l := list.New()
179 m := map[pref.FieldNumber]*list.Element{}
Joe Tsaie2afdc22018-10-25 14:06:56 -0700180 for len(b) > 0 {
181 num, _, n := wire.ConsumeField(b)
Joe Tsai2d5a1692018-10-29 02:10:42 -0700182 if e, ok := m[num]; ok {
183 x := e.Value.(*entry)
184 x.raw = append(x.raw, b[:n]...)
185 l.MoveToBack(e)
186 } else {
187 x := &entry{num: num}
188 x.raw = append(x.raw, b[:n]...)
189 m[num] = l.PushBack(x)
Joe Tsaie2afdc22018-10-25 14:06:56 -0700190 }
Joe Tsaie2afdc22018-10-25 14:06:56 -0700191 b = b[n:]
192 }
193
194 // Iterate over all the raw fields.
195 // This ranges over a snapshot of the current state such that mutations
196 // while ranging are not observable.
197 //
198 // Runtime complexity: O(n)
Joe Tsai2d5a1692018-10-29 02:10:42 -0700199 for e := l.Front(); e != nil; e = e.Next() {
200 x := e.Value.(*entry)
Joe Tsaie2afdc22018-10-25 14:06:56 -0700201 if !f(x.num, x.raw) {
202 return
203 }
204 }
205}
206
207func (fs *legacyUnknownBytes) IsSupported() bool {
208 return true
209}