discard.go (1618B)
1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package proto 6 7 import ( 8 "google.golang.org/protobuf/reflect/protoreflect" 9 ) 10 11 // DiscardUnknown recursively discards all unknown fields from this message 12 // and all embedded messages. 13 // 14 // When unmarshaling a message with unrecognized fields, the tags and values 15 // of such fields are preserved in the Message. This allows a later call to 16 // marshal to be able to produce a message that continues to have those 17 // unrecognized fields. To avoid this, DiscardUnknown is used to 18 // explicitly clear the unknown fields after unmarshaling. 19 func DiscardUnknown(m Message) { 20 if m != nil { 21 discardUnknown(MessageReflect(m)) 22 } 23 } 24 25 func discardUnknown(m protoreflect.Message) { 26 m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool { 27 switch { 28 // Handle singular message. 29 case fd.Cardinality() != protoreflect.Repeated: 30 if fd.Message() != nil { 31 discardUnknown(m.Get(fd).Message()) 32 } 33 // Handle list of messages. 34 case fd.IsList(): 35 if fd.Message() != nil { 36 ls := m.Get(fd).List() 37 for i := 0; i < ls.Len(); i++ { 38 discardUnknown(ls.Get(i).Message()) 39 } 40 } 41 // Handle map of messages. 42 case fd.IsMap(): 43 if fd.MapValue().Message() != nil { 44 ms := m.Get(fd).Map() 45 ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool { 46 discardUnknown(v.Message()) 47 return true 48 }) 49 } 50 } 51 return true 52 }) 53 54 // Discard unknown fields. 55 if len(m.GetUnknown()) > 0 { 56 m.SetUnknown(nil) 57 } 58 }