// 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" papi "github.com/golang/protobuf/protoapi" "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 { if p.p.IsNil() { return emptyUnknownFields{} } rv := p.p.Apply(fieldOffset).AsValueOf(bytesType) return (*legacyUnknownBytes)(rv.Interface().(*[]byte)) } extFunc := makeLegacyExtensionMapFunc(t) if extFunc != nil { return func(p *messageDataType) pref.UnknownFields { if p.p.IsNil() { return emptyUnknownFields{} } 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 papi.ExtensionFields r pref.FieldRanges } func (fs *legacyUnknownBytesAndExtensionMap) Len() int { n := fs.u.Len() fs.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) 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 papi.ExtensionField) 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 }