internal: move usePresenceForField to internal/filedesc
The presence bitmap decision logic is based on the field descriptor,
and in a follow-up CL I want to make both, the runtime and the code
generator, use the same code, so the internal/filedesc package
seems like a good location.
Change-Id: I0216249e00295b3194aaeceb7144ee7cff8dd7ef
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/670515
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Lasse Folger <[email protected]>
diff --git a/internal/filedesc/presence.go b/internal/filedesc/presence.go
new file mode 100644
index 0000000..a12ec97
--- /dev/null
+++ b/internal/filedesc/presence.go
@@ -0,0 +1,33 @@
+// Copyright 2025 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 filedesc
+
+import "google.golang.org/protobuf/reflect/protoreflect"
+
+// UsePresenceForField reports whether the presence bitmap should be used for
+// the specified field.
+func UsePresenceForField(fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
+ switch {
+ case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
+ // Oneof fields never use the presence bitmap.
+ //
+ // Synthetic oneofs are an exception: Those are used to implement proto3
+ // optional fields and hence should follow non-oneof field semantics.
+ return false, false
+
+ case fd.IsMap():
+ // Map-typed fields never use the presence bitmap.
+ return false, false
+
+ case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
+ // Lazy fields always use the presence bitmap (only messages can be lazy).
+ isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
+ return isLazy, isLazy
+
+ default:
+ // If the field has presence, use the presence bitmap.
+ return fd.HasPresence(), false
+ }
+}
diff --git a/internal/impl/codec_message_opaque.go b/internal/impl/codec_message_opaque.go
index 41c1f74..bdad12a 100644
--- a/internal/impl/codec_message_opaque.go
+++ b/internal/impl/codec_message_opaque.go
@@ -11,6 +11,7 @@
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset"
+ "google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
@@ -80,7 +81,7 @@
// permit us to skip over definitely-unset fields at marshal time.
var hasPresence bool
- hasPresence, cf.isLazy = usePresenceForField(si, fd)
+ hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
if hasPresence {
cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
diff --git a/internal/impl/message_opaque.go b/internal/impl/message_opaque.go
index e6b3e41..63a731b 100644
--- a/internal/impl/message_opaque.go
+++ b/internal/impl/message_opaque.go
@@ -11,6 +11,7 @@
"strings"
"sync/atomic"
+ "google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/reflect/protoreflect"
)
@@ -53,7 +54,7 @@
fd := fds.Get(i)
fs := si.fieldsByNumber[fd.Number()]
var fi fieldInfo
- usePresence, _ := usePresenceForField(si, fd)
+ usePresence, _ := filedesc.UsePresenceForField(fd)
switch {
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
@@ -598,29 +599,3 @@
func (mi *MessageInfo) present(p pointer, index uint32) bool {
return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
}
-
-// usePresenceForField reports whether the specified field gets an entry in the
-// presence bitmap.
-func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
- switch {
- case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
- // Oneof fields never use the presence bitmap.
- //
- // Synthetic oneofs are an exception: Those are used to implement proto3
- // optional fields and hence should follow non-oneof field semantics.
- return false, false
-
- case fd.IsMap():
- // Map-typed fields never use the presence bitmap.
- return false, false
-
- case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
- // Lazy fields always use the presence bitmap (only messages can be lazy).
- isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
- return isLazy, isLazy
-
- default:
- // If the field has presence, use the presence bitmap.
- return fd.HasPresence(), false
- }
-}