123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- // Copyright 2019 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 proto
- import (
- "github.com/golang/protobuf/internal/wire"
- pref "google.golang.org/protobuf/reflect/protoreflect"
- "google.golang.org/protobuf/runtime/protoimpl"
- )
- // DiscardUnknown recursively discards all unknown fields from this message
- // and all embedded messages.
- //
- // When unmarshaling a message with unrecognized fields, the tags and values
- // of such fields are preserved in the Message. This allows a later call to
- // marshal to be able to produce a message that continues to have those
- // unrecognized fields. To avoid this, DiscardUnknown is used to
- // explicitly clear the unknown fields after unmarshaling.
- //
- // For proto2 messages, the unknown fields of message extensions are only
- // discarded from messages that have been accessed via GetExtension.
- func DiscardUnknown(m Message) {
- if m == nil {
- return
- }
- discardUnknown(protoimpl.X.MessageOf(m))
- }
- func discardUnknown(m pref.Message) {
- m.Range(func(fd pref.FieldDescriptor, val pref.Value) bool {
- switch {
- // Handle singular message.
- case fd.Cardinality() != pref.Repeated:
- if fd.Message() != nil {
- discardUnknown(m.Get(fd).Message())
- }
- // Handle list of messages.
- case fd.IsList():
- if fd.Message() != nil {
- ls := m.Get(fd).List()
- for i := 0; i < ls.Len(); i++ {
- discardUnknown(ls.Get(i).Message())
- }
- }
- // Handle map of messages.
- case fd.IsMap():
- if fd.MapValue().Message() != nil {
- ms := m.Get(fd).Map()
- ms.Range(func(_ pref.MapKey, v pref.Value) bool {
- discardUnknown(v.Message())
- return true
- })
- }
- }
- return true
- })
- // Discard unknown fields.
- var bo pref.RawFields
- extRanges := m.Descriptor().ExtensionRanges()
- for bi := m.GetUnknown(); len(bi) > 0; {
- // NOTE: Historically, this function did not discard unknown fields
- // that were within the extension field ranges.
- num, _, n := wire.ConsumeField(bi)
- if extRanges.Has(num) {
- bo = append(bo, bi[:n]...)
- }
- bi = bi[n:]
- }
- if bi := m.GetUnknown(); len(bi) != len(bo) {
- m.SetUnknown(bo)
- }
- }
|