| // 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" |
| ) |
| |
| // SetDefaults sets unpopulated scalar fields to their default values. |
| // Fields within a oneof are not set even if they have a default value. |
| // SetDefaults is recursively called upon any populated message fields. |
| func SetDefaults(m Message) { |
| if m != nil { |
| setDefaults(MessageReflect(m)) |
| } |
| } |
| |
| func setDefaults(m protoreflect.Message) { |
| fds := m.Descriptor().Fields() |
| for i := 0; i < fds.Len(); i++ { |
| fd := fds.Get(i) |
| if !m.Has(fd) { |
| if fd.HasDefault() && fd.ContainingOneof() == nil { |
| v := fd.Default() |
| if fd.Kind() == protoreflect.BytesKind { |
| v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes |
| } |
| m.Set(fd, v) |
| } |
| continue |
| } |
| } |
| |
| m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { |
| switch { |
| // Handle singular message. |
| case fd.Cardinality() != protoreflect.Repeated: |
| if fd.Message() != nil { |
| setDefaults(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++ { |
| setDefaults(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 { |
| setDefaults(v.Message()) |
| return true |
| }) |
| } |
| } |
| return true |
| }) |
| } |