xref: /aosp_15_r20/external/golang-protobuf/proto/checkinit.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage proto
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/errors"
9*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
10*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/runtime/protoiface"
11*1c12ee1eSDan Willemsen)
12*1c12ee1eSDan Willemsen
13*1c12ee1eSDan Willemsen// CheckInitialized returns an error if any required fields in m are not set.
14*1c12ee1eSDan Willemsenfunc CheckInitialized(m Message) error {
15*1c12ee1eSDan Willemsen	// Treat a nil message interface as an "untyped" empty message,
16*1c12ee1eSDan Willemsen	// which we assume to have no required fields.
17*1c12ee1eSDan Willemsen	if m == nil {
18*1c12ee1eSDan Willemsen		return nil
19*1c12ee1eSDan Willemsen	}
20*1c12ee1eSDan Willemsen
21*1c12ee1eSDan Willemsen	return checkInitialized(m.ProtoReflect())
22*1c12ee1eSDan Willemsen}
23*1c12ee1eSDan Willemsen
24*1c12ee1eSDan Willemsen// CheckInitialized returns an error if any required fields in m are not set.
25*1c12ee1eSDan Willemsenfunc checkInitialized(m protoreflect.Message) error {
26*1c12ee1eSDan Willemsen	if methods := protoMethods(m); methods != nil && methods.CheckInitialized != nil {
27*1c12ee1eSDan Willemsen		_, err := methods.CheckInitialized(protoiface.CheckInitializedInput{
28*1c12ee1eSDan Willemsen			Message: m,
29*1c12ee1eSDan Willemsen		})
30*1c12ee1eSDan Willemsen		return err
31*1c12ee1eSDan Willemsen	}
32*1c12ee1eSDan Willemsen	return checkInitializedSlow(m)
33*1c12ee1eSDan Willemsen}
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsenfunc checkInitializedSlow(m protoreflect.Message) error {
36*1c12ee1eSDan Willemsen	md := m.Descriptor()
37*1c12ee1eSDan Willemsen	fds := md.Fields()
38*1c12ee1eSDan Willemsen	for i, nums := 0, md.RequiredNumbers(); i < nums.Len(); i++ {
39*1c12ee1eSDan Willemsen		fd := fds.ByNumber(nums.Get(i))
40*1c12ee1eSDan Willemsen		if !m.Has(fd) {
41*1c12ee1eSDan Willemsen			return errors.RequiredNotSet(string(fd.FullName()))
42*1c12ee1eSDan Willemsen		}
43*1c12ee1eSDan Willemsen	}
44*1c12ee1eSDan Willemsen	var err error
45*1c12ee1eSDan Willemsen	m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
46*1c12ee1eSDan Willemsen		switch {
47*1c12ee1eSDan Willemsen		case fd.IsList():
48*1c12ee1eSDan Willemsen			if fd.Message() == nil {
49*1c12ee1eSDan Willemsen				return true
50*1c12ee1eSDan Willemsen			}
51*1c12ee1eSDan Willemsen			for i, list := 0, v.List(); i < list.Len() && err == nil; i++ {
52*1c12ee1eSDan Willemsen				err = checkInitialized(list.Get(i).Message())
53*1c12ee1eSDan Willemsen			}
54*1c12ee1eSDan Willemsen		case fd.IsMap():
55*1c12ee1eSDan Willemsen			if fd.MapValue().Message() == nil {
56*1c12ee1eSDan Willemsen				return true
57*1c12ee1eSDan Willemsen			}
58*1c12ee1eSDan Willemsen			v.Map().Range(func(key protoreflect.MapKey, v protoreflect.Value) bool {
59*1c12ee1eSDan Willemsen				err = checkInitialized(v.Message())
60*1c12ee1eSDan Willemsen				return err == nil
61*1c12ee1eSDan Willemsen			})
62*1c12ee1eSDan Willemsen		default:
63*1c12ee1eSDan Willemsen			if fd.Message() == nil {
64*1c12ee1eSDan Willemsen				return true
65*1c12ee1eSDan Willemsen			}
66*1c12ee1eSDan Willemsen			err = checkInitialized(v.Message())
67*1c12ee1eSDan Willemsen		}
68*1c12ee1eSDan Willemsen		return err == nil
69*1c12ee1eSDan Willemsen	})
70*1c12ee1eSDan Willemsen	return err
71*1c12ee1eSDan Willemsen}
72