| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- // Copyright 2018 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package impl
- import (
- "container/list"
- "reflect"
- "sort"
- "github.com/golang/protobuf/v2/internal/encoding/wire"
- pref "github.com/golang/protobuf/v2/reflect/protoreflect"
- )
- var bytesType = reflect.TypeOf([]byte(nil))
- func makeLegacyUnknownFieldsFunc(t reflect.Type) func(p *messageDataType) pref.UnknownFields {
- fu, ok := t.FieldByName("XXX_unrecognized")
- if !ok || fu.Type != bytesType {
- return nil
- }
- fieldOffset := offsetOf(fu)
- unkFunc := func(p *messageDataType) pref.UnknownFields {
- rv := p.p.apply(fieldOffset).asType(bytesType)
- return (*legacyUnknownBytes)(rv.Interface().(*[]byte))
- }
- extFunc := makeLegacyExtensionMapFunc(t)
- if extFunc != nil {
- return func(p *messageDataType) pref.UnknownFields {
- return &legacyUnknownBytesAndExtensionMap{
- unkFunc(p), extFunc(p), p.mi.Type.ExtensionRanges(),
- }
- }
- }
- return unkFunc
- }
- // legacyUnknownBytesAndExtensionMap is a wrapper around both XXX_unrecognized
- // and also the extension field map.
- type legacyUnknownBytesAndExtensionMap struct {
- u pref.UnknownFields
- x legacyExtensionIface
- r pref.FieldRanges
- }
- func (fs *legacyUnknownBytesAndExtensionMap) Len() int {
- n := fs.u.Len()
- fs.x.Range(func(_ pref.FieldNumber, x legacyExtensionEntry) bool {
- if len(x.raw) > 0 {
- n++
- }
- return true
- })
- return n
- }
- func (fs *legacyUnknownBytesAndExtensionMap) Get(num pref.FieldNumber) (raw pref.RawFields) {
- if fs.r.Has(num) {
- return fs.x.Get(num).raw
- }
- return fs.u.Get(num)
- }
- func (fs *legacyUnknownBytesAndExtensionMap) Set(num pref.FieldNumber, raw pref.RawFields) {
- if fs.r.Has(num) {
- x := fs.x.Get(num)
- x.raw = raw
- fs.x.Set(num, x)
- return
- }
- fs.u.Set(num, raw)
- }
- func (fs *legacyUnknownBytesAndExtensionMap) Range(f func(pref.FieldNumber, pref.RawFields) bool) {
- // Range over unknown fields not in the extension range.
- // Create a closure around f to capture whether iteration terminated early.
- var stop bool
- fs.u.Range(func(n pref.FieldNumber, b pref.RawFields) bool {
- stop = stop || !f(n, b)
- return !stop
- })
- if stop {
- return
- }
- // Range over unknown fields in the extension range in ascending order
- // to ensure protoreflect.UnknownFields.Range remains deterministic.
- type entry struct {
- num pref.FieldNumber
- raw pref.RawFields
- }
- var xs []entry
- fs.x.Range(func(n pref.FieldNumber, x legacyExtensionEntry) bool {
- if len(x.raw) > 0 {
- xs = append(xs, entry{n, x.raw})
- }
- return true
- })
- sort.Slice(xs, func(i, j int) bool { return xs[i].num < xs[j].num })
- for _, x := range xs {
- if !f(x.num, x.raw) {
- return
- }
- }
- }
- func (fs *legacyUnknownBytesAndExtensionMap) IsSupported() bool {
- return true
- }
- // legacyUnknownBytes is a wrapper around XXX_unrecognized that implements
- // the protoreflect.UnknownFields interface. This is challenging since we are
- // limited to a []byte, so we do not have much flexibility in the choice
- // of data structure that would have been ideal.
- type legacyUnknownBytes []byte
- func (fs *legacyUnknownBytes) Len() int {
- // Runtime complexity: O(n)
- b := *fs
- m := map[pref.FieldNumber]bool{}
- for len(b) > 0 {
- num, _, n := wire.ConsumeField(b)
- m[num] = true
- b = b[n:]
- }
- return len(m)
- }
- func (fs *legacyUnknownBytes) Get(num pref.FieldNumber) (raw pref.RawFields) {
- // Runtime complexity: O(n)
- b := *fs
- for len(b) > 0 {
- num2, _, n := wire.ConsumeField(b)
- if num == num2 {
- raw = append(raw, b[:n]...)
- }
- b = b[n:]
- }
- return raw
- }
- func (fs *legacyUnknownBytes) Set(num pref.FieldNumber, raw pref.RawFields) {
- num2, _, _ := wire.ConsumeTag(raw)
- if len(raw) > 0 && (!raw.IsValid() || num != num2) {
- panic("invalid raw fields")
- }
- // Remove all current fields of num.
- // Runtime complexity: O(n)
- b := *fs
- out := (*fs)[:0]
- for len(b) > 0 {
- num2, _, n := wire.ConsumeField(b)
- if num != num2 {
- out = append(out, b[:n]...)
- }
- b = b[n:]
- }
- *fs = out
- // Append new fields of num.
- *fs = append(*fs, raw...)
- }
- func (fs *legacyUnknownBytes) Range(f func(pref.FieldNumber, pref.RawFields) bool) {
- type entry struct {
- num pref.FieldNumber
- raw pref.RawFields
- }
- // Collect up a list of all the raw fields.
- // We preserve the order such that the latest encountered fields
- // are presented at the end.
- //
- // Runtime complexity: O(n)
- b := *fs
- l := list.New()
- m := map[pref.FieldNumber]*list.Element{}
- for len(b) > 0 {
- num, _, n := wire.ConsumeField(b)
- if e, ok := m[num]; ok {
- x := e.Value.(*entry)
- x.raw = append(x.raw, b[:n]...)
- l.MoveToBack(e)
- } else {
- x := &entry{num: num}
- x.raw = append(x.raw, b[:n]...)
- m[num] = l.PushBack(x)
- }
- b = b[n:]
- }
- // Iterate over all the raw fields.
- // This ranges over a snapshot of the current state such that mutations
- // while ranging are not observable.
- //
- // Runtime complexity: O(n)
- for e := l.Front(); e != nil; e = e.Next() {
- x := e.Value.(*entry)
- if !f(x.num, x.raw) {
- return
- }
- }
- }
- func (fs *legacyUnknownBytes) IsSupported() bool {
- return true
- }
|