defaults.go (1637B)
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 // SetDefaults sets unpopulated scalar fields to their default values. 12 // Fields within a oneof are not set even if they have a default value. 13 // SetDefaults is recursively called upon any populated message fields. 14 func SetDefaults(m Message) { 15 if m != nil { 16 setDefaults(MessageReflect(m)) 17 } 18 } 19 20 func setDefaults(m protoreflect.Message) { 21 fds := m.Descriptor().Fields() 22 for i := 0; i < fds.Len(); i++ { 23 fd := fds.Get(i) 24 if !m.Has(fd) { 25 if fd.HasDefault() && fd.ContainingOneof() == nil { 26 v := fd.Default() 27 if fd.Kind() == protoreflect.BytesKind { 28 v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes 29 } 30 m.Set(fd, v) 31 } 32 continue 33 } 34 } 35 36 m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { 37 switch { 38 // Handle singular message. 39 case fd.Cardinality() != protoreflect.Repeated: 40 if fd.Message() != nil { 41 setDefaults(m.Get(fd).Message()) 42 } 43 // Handle list of messages. 44 case fd.IsList(): 45 if fd.Message() != nil { 46 ls := m.Get(fd).List() 47 for i := 0; i < ls.Len(); i++ { 48 setDefaults(ls.Get(i).Message()) 49 } 50 } 51 // Handle map of messages. 52 case fd.IsMap(): 53 if fd.MapValue().Message() != nil { 54 ms := m.Get(fd).Map() 55 ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool { 56 setDefaults(v.Message()) 57 return true 58 }) 59 } 60 } 61 return true 62 }) 63 }