// 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 ( "google.golang.org/protobuf/reflect/protoreflect" ) // 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. func DiscardUnknown(m Message) { if m != nil { discardUnknown(MessageReflect(m)) } } func discardUnknown(m protoreflect.Message) { m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool { switch { // Handle singular message. case fd.Cardinality() != protoreflect.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(_ protoreflect.MapKey, v protoreflect.Value) bool { discardUnknown(v.Message()) return true }) } } return true }) // Discard unknown fields. if len(m.GetUnknown()) > 0 { m.SetUnknown(nil) } }