| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- // 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"
- "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)
- return func(p *messageDataType) pref.UnknownFields {
- if p.p.IsNil() {
- return emptyUnknownFields{}
- }
- rv := p.p.Apply(fieldOffset).AsValueOf(bytesType)
- return (*legacyUnknownBytes)(rv.Interface().(*[]byte))
- }
- }
- // 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
- }
|