amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 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. |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 4 | |
| 5 | package proto |
| 6 | |
| 7 | import ( |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 8 | "google.golang.org/protobuf/reflect/protoreflect" |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 9 | ) |
| 10 | |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 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. |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 19 | func DiscardUnknown(m Message) { |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 20 | if m != nil { |
| 21 | discardUnknown(MessageReflect(m)) |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 22 | } |
| 23 | } |
| 24 | |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 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()) |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 39 | } |
| 40 | } |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 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 | }) |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 49 | } |
| 50 | } |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 51 | return true |
| 52 | }) |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 53 | |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame^] | 54 | // Discard unknown fields. |
| 55 | if len(m.GetUnknown()) > 0 { |
| 56 | m.SetUnknown(nil) |
Matteo Scandolo | a6a3aee | 2019-11-26 13:30:14 -0700 | [diff] [blame] | 57 | } |
| 58 | } |