// Copyright 2024 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 internal_gengo

import (
	"fmt"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"

	"google.golang.org/protobuf/compiler/protogen"
	"google.golang.org/protobuf/internal/genid"
	"google.golang.org/protobuf/reflect/protoreflect"

	"google.golang.org/protobuf/types/descriptorpb"
)

func opaqueGenMessageHook(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) bool {
	opaqueGenMessage(g, f, message)
	return true
}

func opaqueGenMessage(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
	// Message type declaration.
	g.AnnotateSymbol(message.GoIdent.GoName, protogen.Annotation{Location: message.Location})
	leadingComments := appendDeprecationSuffix(message.Comments.Leading,
		message.Desc.ParentFile(),
		message.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
	g.P(leadingComments,
		"type ", message.GoIdent, " struct {")

	sf := f.allMessageFieldsByPtr[message]
	if sf == nil {
		sf = new(structFields)
		f.allMessageFieldsByPtr[message] = sf
	}

	var tags structTags
	switch {
	case message.isOpen():
		tags = structTags{{"protogen", "open.v1"}}
	case message.isHybrid():
		tags = structTags{{"protogen", "hybrid.v1"}}
	case message.isOpaque():
		tags = structTags{{"protogen", "opaque.v1"}}
	}

	g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"), tags)
	sf.append(genid.State_goname)
	fields := message.Fields
	for _, field := range fields {
		opaqueGenMessageField(g, f, message, field, sf)
	}
	opaqueGenMessageInternalFields(g, f, message, sf)
	g.P("}")
	g.P()

	genMessageKnownFunctions(g, f, message)
	genMessageDefaultDecls(g, f, message)
	opaqueGenMessageMethods(g, f, message)
	opaqueGenMessageBuilder(g, f, message)
	opaqueGenOneofWrapperTypes(g, f, message)
}

// opaqueGenMessageField generates a struct field.
func opaqueGenMessageField(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field, sf *structFields) {
	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
		// It would be a bit simpler to iterate over the oneofs below,
		// but generating the field here keeps the contents of the Go
		// struct in the same order as the contents of the source
		// .proto file.
		if field != oneof.Fields[0] {
			return
		}
		opaqueGenOneofFields(g, f, message, oneof, sf)
		return
	}

	goType, pointer := opaqueFieldGoType(g, f, message, field)
	if pointer {
		goType = "*" + goType
	}
	protobufTagValue := fieldProtobufTagValue(field)
	jsonTagValue := fieldJSONTagValue(field)
	if g.InternalStripForEditionsDiff() {
		if field.Desc.ContainingOneof() != nil && field.Desc.ContainingOneof().IsSynthetic() {
			protobufTagValue = strings.ReplaceAll(protobufTagValue, ",oneof", "")
		}
		protobufTagValue = strings.ReplaceAll(protobufTagValue, ",proto3", "")
	}
	tags := structTags{
		{"protobuf", protobufTagValue},
		{"json", jsonTagValue},
	}
	if field.Desc.IsMap() {
		keyTagValue := fieldProtobufTagValue(field.Message.Fields[0])
		valTagValue := fieldProtobufTagValue(field.Message.Fields[1])
		keyTagValue = strings.ReplaceAll(keyTagValue, ",proto3", "")
		valTagValue = strings.ReplaceAll(valTagValue, ",proto3", "")
		tags = append(tags, structTags{
			{"protobuf_key", keyTagValue},
			{"protobuf_val", valTagValue},
		}...)
	}

	name := field.GoName
	if field.Desc.IsWeak() {
		g.P("// Deprecated: Do not use. This will be deleted in the near future.")
		name = genid.WeakFieldPrefix_goname + name
	} else if message.isOpaque() {
		name = "xxx_hidden_" + name
	}

	if message.isOpaque() && !field.Desc.IsWeak() {
		g.P(name, " ", goType, tags)
		sf.append(name)
		if message.isTracked {
			g.P("// Deprecated: Do not use. This will be deleted in the near future.")
			g.P("XXX_ft_", field.GoName, " struct{} `go:\"track\"`")
			sf.append("XXX_ft_" + field.GoName)
		}
	} else {
		if message.isTracked {
			tags = append(tags, structTags{
				{"go", "track"},
			}...)
		}
		g.AnnotateSymbol(field.Parent.GoIdent.GoName+"."+name, protogen.Annotation{Location: field.Location})
		leadingComments := appendDeprecationSuffix(field.Comments.Leading,
			field.Desc.ParentFile(),
			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
		g.P(leadingComments,
			name, " ", goType, tags,
			trailingComment(field.Comments.Trailing))
		sf.append(name)
	}
}

// opaqueGenOneofFields generates the message fields for a oneof.
func opaqueGenOneofFields(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof, sf *structFields) {
	tags := structTags{
		{"protobuf_oneof", string(oneof.Desc.Name())},
	}
	if message.isTracked {
		tags = append(tags, structTags{
			{"go", "track"},
		}...)
	}

	oneofName := opaqueOneofFieldName(oneof, message.isOpaque())
	goType := opaqueOneofInterfaceName(oneof)

	if message.isOpaque() {
		g.P(oneofName, " ", goType, tags)
		sf.append(oneofName)
		if message.isTracked {
			g.P("// Deprecated: Do not use. This will be deleted in the near future.")
			g.P("XXX_ft_", oneof.GoName, " struct{} `go:\"track\"`")
			sf.append("XXX_ft_" + oneof.GoName)
		}
		return
	}

	leadingComments := oneof.Comments.Leading
	if leadingComments != "" {
		leadingComments += "\n"
	}
	// NOTE(rsc): The extra \n here is working around #52605,
	// making the comment be in Go 1.19 doc comment format
	// even though it's not really a doc comment.
	ss := []string{" Types that are valid to be assigned to ", oneofName, ":\n\n"}
	for _, field := range oneof.Fields {
		ss = append(ss, "\t*"+opaqueFieldOneofType(field, message.isOpaque()).GoName+"\n")
	}
	leadingComments += protogen.Comments(strings.Join(ss, ""))
	g.P(leadingComments, oneofName, " ", goType, tags)
	sf.append(oneofName)
}

// opaqueGenMessageInternalFields adds additional XXX_ fields to a message struct.
func opaqueGenMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, sf *structFields) {
	if opaqueNeedsPresenceArray(message) {
		if opaqueNeedsLazyStruct(message) {
			g.P("// Deprecated: Do not use. This will be deleted in the near future.")
			g.P("XXX_lazyUnmarshalInfo ", protoimplPackage.Ident("LazyUnmarshalInfo"))
			sf.append("XXX_lazyUnmarshalInfo")
		}
		g.P("XXX_raceDetectHookData ", protoimplPackage.Ident("RaceDetectHookData"))
		sf.append("XXX_raceDetectHookData")

		// Presence must be stored in a data type no larger than 32 bit:
		//
		// Presence used to be a uint64, accessed with atomic.LoadUint64, but it
		// turns out that on 32-bit platforms like GOARCH=arm, the struct field
		// was 32-bit aligned (not 64-bit aligned) and hence atomic accesses
		// failed.
		//
		// The easiest solution was to switch to a uint32 on all platforms,
		// which did not come with a performance penalty.
		g.P("XXX_presence [", (opaqueNumPresenceFields(message)+31)/32, "]uint32")
		sf.append("XXX_presence")
	}
	if message.hasWeak {
		g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
		sf.append(genid.WeakFields_goname)
	}
	if message.Desc.ExtensionRanges().Len() > 0 {
		g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
		sf.append(genid.ExtensionFields_goname)
	}
	g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
	sf.append(genid.UnknownFields_goname)
	g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
	sf.append(genid.SizeCache_goname)
}

func opaqueGenMessageMethods(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
	genMessageBaseMethods(g, f, message)

	isRepeated := func(field *protogen.Field) bool {
		return field.Desc.Cardinality() == protoreflect.Repeated
	}

	for _, field := range message.Fields {
		if isFirstOneofField(field) && !message.isOpaque() {
			opaqueGenGetOneof(g, f, message, field.Oneof)
		}
		opaqueGenGet(g, f, message, field)
	}
	for _, field := range message.Fields {
		// For the plain open mode, we only have set methods for weak fields.
		if message.isOpen() && !field.Desc.IsWeak() {
			continue
		}
		opaqueGenSet(g, f, message, field)
	}
	for _, field := range message.Fields {
		// Open API does not have Has method.
		// Repeated (includes map) fields do not have Has method.
		if message.isOpen() || isRepeated(field) {
			continue
		}

		if !field.Desc.HasPresence() {
			continue
		}

		if isFirstOneofField(field) {
			opaqueGenHasOneof(g, f, message, field.Oneof)
		}
		opaqueGenHas(g, f, message, field)
	}
	for _, field := range message.Fields {
		// Open API does not have Clear method.
		// Repeated (includes map) fields do not have Clear method.
		if message.isOpen() || isRepeated(field) {
			continue
		}
		if !field.Desc.HasPresence() {
			continue
		}

		if isFirstOneofField(field) {
			opaqueGenClearOneof(g, f, message, field.Oneof)
		}
		opaqueGenClear(g, f, message, field)
	}
	// Plain open protos do not have which methods.
	if !message.isOpen() {
		opaqueGenWhichOneof(g, f, message)
	}

	if g.InternalStripForEditionsDiff() {
		return
	}
}

func isLazy(field *protogen.Field) bool {
	// Prerequisite: field is of kind message
	if field.Message == nil {
		return false
	}

	// Was the field marked as [lazy = true] in the .proto file?
	fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
	return fopts.GetLazy()
}

// opaqueGenGet generates a Get method for a field.
func opaqueGenGet(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
	goType, pointer := opaqueFieldGoType(g, f, message, field)
	getterName, bcName := field.MethodName("Get")

	// If we need a backwards compatible getter name, we add it now.
	if bcName != "" {
		defer func() {
			g.P("// Deprecated: Use ", getterName, " instead.")
			g.P("func (x *", message.GoIdent, ") ", bcName, "() ", goType, " {")
			g.P("return x.", getterName, "()")
			g.P("}")
			g.P()
		}()
	}

	leadingComments := appendDeprecationSuffix("",
		field.Desc.ParentFile(),
		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
	fieldtrackNoInterface(g, message.isTracked)
	g.AnnotateSymbol(message.GoIdent.GoName+"."+getterName, protogen.Annotation{Location: field.Location})

	// Weak field.
	if field.Desc.IsWeak() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", protoPackage.Ident("Message"), "{")
		g.P("var w ", protoimplPackage.Ident("WeakFields"))
		g.P("if x != nil {")
		g.P("w = x.", genid.WeakFields_goname)
		if message.isTracked {
			g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
		}
		g.P("}")
		g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
		g.P("}")
		g.P()
		return
	}

	defaultValue := fieldDefaultValue(g, f, message, field)

	// Oneof field.
	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
		structPtr := "x"
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, " {")
		g.P("if x != nil {")
		if message.isOpaque() && message.isTracked {
			g.P("_ = ", structPtr, ".XXX_ft_", field.Oneof.GoName)
		}
		g.P("if x, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), "); ok {")
		g.P("return x.", field.GoName)
		g.P("}")
		// End if m != nil {.
		g.P("}")
		g.P("return ", defaultValue)
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field for open type message.
	if !message.isOpaque() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, " {")
		if !field.Desc.HasPresence() || defaultValue == "nil" {
			g.P("if x != nil {")
		} else {
			g.P("if x != nil && x.", field.GoName, " != nil {")
		}
		star := ""
		if pointer {
			star = "*"
		}
		g.P("return ", star, " x.", field.GoName)
		g.P("}")
		g.P("return ", defaultValue)
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field for opaque type message.
	g.P(leadingComments, "func (x *", message.GoIdent, ") ", getterName, "() ", goType, "{")
	structPtr := "x"
	g.P("if x != nil {")
	if message.isTracked {
		g.P("_ = ", structPtr, ".XXX_ft_", field.GoName)
	}
	if usePresence(message, field) {
		pi := opaqueFieldPresenceIndex(field)
		ai := pi / 32
		// For
		//
		//  1. Message fields of lazy messages (unmarshalled lazily),
		//  2. Fields with a default value,
		//  3. Closed enums
		//
		// ...we check presence, but for other fields using presence, we can return
		// whatever is there and it should be correct regardless of presence, which
		// saves us an atomic operation.
		isEnum := field.Desc.Kind() == protoreflect.EnumKind
		usePresenceForRead := (isLazy(field)) ||
			field.Desc.HasDefault() || isEnum

		if usePresenceForRead {
			g.P("if ", protoimplPackage.Ident("X"), ".Present(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ") {")
		}
		// For lazy, check if pointer is nil and optionally unmarshal
		if isLazy(field) {
			// Since pointer to lazily unmarshaled sub-message can be written during a conceptual
			// "read" operation, all read/write accesses to the pointer must be atomic.  This
			// function gets inlined on x86 as just a simple get and compare. Still need to make the
			// slice accesses be atomic.
			g.P("if ", protoimplPackage.Ident("X"), ".AtomicCheckPointerIsNil(&", structPtr, ".xxx_hidden_", field.GoName, ") {")
			g.P(protoimplPackage.Ident("X"), ".UnmarshalField(", structPtr, ", ", field.Desc.Number(), ")")
			g.P("}")
		}
		if field.Message == nil || field.Desc.IsMap() {
			star := ""
			if pointer {
				star = "*"
			}
			if pointer {
				g.P("if ", structPtr, ".xxx_hidden_", field.GoName, "!= nil {")
			}

			g.P("return ", star, structPtr, ".xxx_hidden_", field.GoName)
			if pointer {
				g.P("}")
				g.P("return ", defaultValue)
			}
		} else {
			// We need to do an atomic load of the msg pointer field, but cannot explicitly use
			// unsafe pointers here.  We load the value and store into rv, via protoimpl.Pointer,
			// which is aliased to unsafe.Pointer in pointer_unsafe.go, but is aliased to
			// interface{} in pointer_reflect.go
			star := ""
			if pointer {
				star = "*"
			}
			if isLazy(field) {
				g.P("var rv ", star, goType)
				g.P(protoimplPackage.Ident("X"), ".AtomicLoadPointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&rv))")
				g.P("return ", star, "rv")
			} else {
				if pointer {
					g.P("if ", structPtr, ".xxx_hidden_", field.GoName, "!= nil {")
				}
				g.P("return ", star, structPtr, ".xxx_hidden_", field.GoName)
				if pointer {
					g.P("}")
				}
			}
		}
		if usePresenceForRead {
			g.P("}")
		}
	} else if pointer {
		g.P("if ", structPtr, ".xxx_hidden_", field.GoName, " != nil {")
		g.P("return *", structPtr, ".xxx_hidden_", field.GoName)
		g.P("}")
	} else {
		g.P("return ", structPtr, ".xxx_hidden_", field.GoName)
	}
	// End if m != nil {.
	g.P("}")
	g.P("return ", defaultValue)
	g.P("}")
	g.P()
}

// opaqueGenSet generates a Set method for a field.
func opaqueGenSet(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
	goType, pointer := opaqueFieldGoType(g, f, message, field)
	setterName, bcName := field.MethodName("Set")

	// If we need a backwards compatible setter name, we add it now.
	if bcName != "" {
		defer func() {
			g.P("// Deprecated: Use ", setterName, " instead.")
			g.P("func (x *", message.GoIdent, ") ", bcName, "(v ", goType, ") {")
			g.P("x.", setterName, "(v)")
			g.P("}")
			g.P()
		}()
	}

	leadingComments := appendDeprecationSuffix("",
		field.Desc.ParentFile(),
		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
	g.AnnotateSymbol(message.GoIdent.GoName+"."+setterName, protogen.Annotation{
		Location: field.Location,
		Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
	})
	fieldtrackNoInterface(g, message.noInterface)

	// Weak field.
	if field.Desc.IsWeak() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", protoPackage.Ident("Message"), ") {")
		g.P("var w *", protoimplPackage.Ident("WeakFields"))
		g.P("if x != nil {")
		g.P("w = &x.", genid.WeakFields_goname)
		if message.isTracked {
			g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
		}
		g.P("}")
		g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
		g.P("}")
		g.P()
		return
	}

	// Oneof field.
	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
		structPtr := "x"
		if message.isOpaque() && message.isTracked {
			// Add access to zero field for tracking
			g.P(structPtr, ".XXX_ft_", oneof.GoName, " = struct{}{}")
		}
		if field.Desc.Kind() == protoreflect.BytesKind {
			g.P("if v == nil { v = []byte{} }")
		} else if field.Message != nil {
			g.P("if v == nil {")
			g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), "= nil")
			g.P("return")
			g.P("}")
		}
		g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), "= &", opaqueFieldOneofType(field, message.isOpaque()), "{v}")
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field for open type message.
	if !message.isOpaque() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
		if field.Desc.Cardinality() != protoreflect.Repeated && field.Desc.Kind() == protoreflect.BytesKind {
			g.P("if v == nil { v = []byte{} }")
		}
		amp := ""
		if pointer {
			amp = "&"
		}

		v := "v"
		g.P("x.", field.GoName, " = ", amp, v)
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field for opaque type message.
	g.P(leadingComments, "func (x *", message.GoIdent, ") ", setterName, "(v ", goType, ") {")
	structPtr := "x"
	if message.isTracked {
		// Add access to zero field for tracking
		g.P(structPtr, ".XXX_ft_", field.GoName, " = struct{}{}")
	}
	if field.Desc.Cardinality() != protoreflect.Repeated && field.Desc.Kind() == protoreflect.BytesKind {
		g.P("if v == nil { v = []byte{} }")
	}
	amp := ""
	if pointer {
		amp = "&"
	}
	if usePresence(message, field) {
		pi := opaqueFieldPresenceIndex(field)
		ai := pi / 32

		if field.Message != nil && field.Desc.IsList() {
			g.P("var sv *", goType)
			g.P(protoimplPackage.Ident("X"), ".AtomicLoadPointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&sv))")
			g.P("if sv == nil {")
			g.P("sv = &", goType, "{}")
			g.P(protoimplPackage.Ident("X"), ".AtomicInitializePointer(", protoimplPackage.Ident("Pointer"), "(&", structPtr, ".xxx_hidden_", field.GoName, "), ", protoimplPackage.Ident("Pointer"), "(&sv))")
			g.P("}")
			g.P("*sv = v")
			g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
		} else if field.Message != nil && !field.Desc.IsMap() {
			// Only for lazy messages do we need to set pointers atomically
			if isLazy(field) {
				g.P(protoimplPackage.Ident("X"), ".AtomicSetPointer(&", structPtr, ".xxx_hidden_", field.GoName, ", ", amp, "v)")
			} else {
				g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
			}
			// When setting a message or slice of messages to a nil
			// value, we must clear the presence bit, else we will
			// later think that this field still needs to be lazily decoded.
			g.P("if v == nil {")
			g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
			g.P("} else {")
			g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
			g.P("}")
		} else {
			// Any map or non-message, possibly repeated, field that uses presence (proto2 only)
			g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
			// For consistent behaviour with lazy fields, non-map repeated fields should be cleared when
			// the last object is removed. Maps are cleared when set to a nil map.
			if field.Desc.Cardinality() == protoreflect.Repeated { // Includes maps.
				g.P("if v == nil {")
				g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
				g.P("} else {")
			}
			g.P(protoimplPackage.Ident("X"), ".SetPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
			if field.Desc.Cardinality() == protoreflect.Repeated {
				g.P("}")
			}
		}
	} else {
		// proto3 non-lazy fields
		g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", amp, "v")
	}
	g.P("}")
	g.P()
}

// usePresence returns true if the presence map should be used for a field. It
// is always true for lazy message types. It is also true for all scalar fields.
// repeated, map or message fields are not using the presence map.
func usePresence(message *messageInfo, field *protogen.Field) bool {
	if !message.isOpaque() || field.Desc.IsWeak() {
		return false
	}
	return opaqueFieldNeedsPresenceArray(message, field)
}

func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
	// Non optional fields need presence if truly lazy field, i.e. are message fields.
	if isLazy(field) {
		return true
	}
	isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
	return field.Desc.HasPresence() && field.Message == nil && isNotOneof
}

// opaqueGenHas generates a Has method for a field.
func opaqueGenHas(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
	hasserName, _ := field.MethodName("Has")

	leadingComments := appendDeprecationSuffix("",
		field.Desc.ParentFile(),
		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
	g.AnnotateSymbol(message.GoIdent.GoName+"."+hasserName, protogen.Annotation{Location: field.Location})
	fieldtrackNoInterface(g, message.noInterface)

	// Weak field.
	if field.Desc.IsWeak() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
		g.P("var w ", protoimplPackage.Ident("WeakFields"))
		g.P("if x != nil {")
		g.P("w = x.", genid.WeakFields_goname)
		if message.isTracked {
			g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
		}
		g.P("}")
		g.P("return ", protoimplPackage.Ident("X"), ".HasWeak(w, ", field.Desc.Number(), ")")
		g.P("}")
		g.P()
		return
	}

	// Oneof field.
	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
		structPtr := "x"
		g.P("if ", structPtr, " == nil {")
		g.P("return false")
		g.P("}")
		if message.isOpaque() && message.isTracked {
			// Add access to zero field for tracking
			g.P("_ = ", structPtr, ".", "XXX_ft_", oneof.GoName)
		}
		g.P("_, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), ")")
		g.P("return ok")
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field in open message.
	if !message.isOpaque() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
		g.P("if x == nil {")
		g.P("return false")
		g.P("}")
		g.P("return ", "x.", field.GoName, " != nil")
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field in opaque message.
	g.P(leadingComments, "func (x *", message.GoIdent, ") ", hasserName, "() bool {")
	g.P("if x == nil {")
	g.P("return false")
	g.P("}")
	structPtr := "x"
	if message.isTracked {
		// Add access to zero field for tracking
		g.P("_ = ", structPtr, ".", "XXX_ft_"+field.GoName)
	}
	if usePresence(message, field) {
		pi := opaqueFieldPresenceIndex(field)
		ai := pi / 32
		g.P("return ", protoimplPackage.Ident("X"), ".Present(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
	} else {
		// Has for proto3 message without presence
		g.P("return ", structPtr, ".xxx_hidden_", field.GoName, " != nil")
	}

	g.P("}")
	g.P()
}

// opaqueGenClear generates a Clear method for a field.
func opaqueGenClear(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) {
	clearerName, _ := field.MethodName("Clear")
	pi := opaqueFieldPresenceIndex(field)
	ai := pi / 32

	leadingComments := appendDeprecationSuffix("",
		field.Desc.ParentFile(),
		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
	g.AnnotateSymbol(message.GoIdent.GoName+"."+clearerName, protogen.Annotation{
		Location: field.Location,
		Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
	})
	fieldtrackNoInterface(g, message.noInterface)

	// Weak field.
	if field.Desc.IsWeak() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
		g.P("var w *", protoimplPackage.Ident("WeakFields"))
		g.P("if x != nil {")
		g.P("w = &x.", genid.WeakFields_goname)
		if message.isTracked {
			g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
		}
		g.P("}")
		g.P(protoimplPackage.Ident("X"), ".ClearWeak(w, ", field.Desc.Number(), ")")
		g.P("}")
		g.P()
		return
	}

	// Oneof field.
	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
		structPtr := "x"
		if message.isOpaque() && message.isTracked {
			// Add access to zero field for tracking
			g.P(structPtr, ".", "XXX_ft_", oneof.GoName, " = struct{}{}")
		}
		g.P("if _, ok := ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), ".(*", opaqueFieldOneofType(field, message.isOpaque()), "); ok {")
		g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " = nil")
		g.P("}")
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field in open message.
	if !message.isOpaque() {
		g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
		g.P("x.", field.GoName, " = nil")
		g.P("}")
		g.P()
		return
	}

	// Non-oneof field in opaque message.
	g.P(leadingComments, "func (x *", message.GoIdent, ") ", clearerName, "() {")
	structPtr := "x"
	if message.isTracked {
		// Add access to zero field for tracking
		g.P(structPtr, ".", "XXX_ft_", field.GoName, " = struct{}{}")
	}

	if usePresence(message, field) {
		g.P(protoimplPackage.Ident("X"), ".ClearPresent(&(", structPtr, ".XXX_presence[", ai, "]),", pi, ")")
	}

	// Avoid needing to read the presence value in Get by ensuring that we set the
	// right zero value (unless we have an explicit default, in which case we
	// revert to presence checking in Get). Rationale: Get is called far more
	// frequently than Clear, it should be as lean as possible.
	zv := opaqueZeroValueForField(g, field)
	// For lazy, (repeated) message fields are unmarshalled lazily. Hence they are
	// assigned atomically in Getters (which are allowed to be called
	// concurrently). Due to this, historically, the code generator would use
	// atomic operations everywhere.
	//
	// TODO(b/291588964): Stop using atomic operations for non-presence fields in
	//                    write calls (Set/Clear). Concurrent reads are allowed,
	//                    but concurrent read/write or write/write are not, we
	//                    shouldn't cater to it.
	if isLazy(field) {
		goType, _ := opaqueFieldGoType(g, f, message, field)
		g.P(protoimplPackage.Ident("X"), ".AtomicSetPointer(&", structPtr, ".xxx_hidden_", field.GoName, ",(", goType, ")(", zv, "))")
	} else if !field.Desc.HasDefault() {
		g.P(structPtr, ".xxx_hidden_", field.GoName, " = ", zv)
	}
	g.P("}")
	g.P()
}

// Determine what value to set a cleared field to.
func opaqueZeroValueForField(g *protogen.GeneratedFile, field *protogen.Field) string {
	if field.Desc.Cardinality() == protoreflect.Repeated {
		return "nil"
	}
	switch field.Desc.Kind() {
	case protoreflect.StringKind:
		return "nil"
	case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
		return "nil"
	case protoreflect.BoolKind:
		return "false"
	case protoreflect.EnumKind:
		return g.QualifiedGoIdent(field.Enum.Values[0].GoIdent)
	default:
		return "0"
	}
}

// opaqueGenGetOneof generates a Get function for a oneof union.
func opaqueGenGetOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
	ifName := opaqueOneofInterfaceName(oneof)
	g.AnnotateSymbol(message.GoIdent.GoName+".Get"+oneof.GoName, protogen.Annotation{Location: oneof.Location})
	fieldtrackNoInterface(g, message.isTracked)
	g.P("func (x *", message.GoIdent.GoName, ") Get", oneof.GoName, "() ", ifName, " {")
	g.P("if x != nil {")
	g.P("return x.", opaqueOneofFieldName(oneof, message.isOpaque()))
	g.P("}")
	g.P("return nil")
	g.P("}")
	g.P()
}

// opaqueGenHasOneof generates a Has function for a oneof union.
func opaqueGenHasOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
	fieldtrackNoInterface(g, message.noInterface)
	hasserName := oneof.MethodName("Has")
	g.P("func (x *", message.GoIdent, ") ", hasserName, "() bool {")
	g.P("if x == nil {")
	g.P("return false")
	g.P("}")
	structPtr := "x"
	if message.isOpaque() && message.isTracked {
		// Add access to zero field for tracking
		g.P("_ = ", structPtr, ".XXX_ft_", oneof.GoName)
	}
	g.P("return ", structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " != nil")
	g.P("}")
	g.P()
}

// opaqueGenClearOneof generates a Clear function for a oneof union.
func opaqueGenClearOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, oneof *protogen.Oneof) {
	fieldtrackNoInterface(g, message.noInterface)
	clearerName := oneof.MethodName("Clear")
	g.P("func (x *", message.GoIdent, ") ", clearerName, "() {")
	structPtr := "x"
	if message.isOpaque() && message.isTracked {
		// Add access to zero field for tracking
		g.P(structPtr, ".", "XXX_ft_", oneof.GoName, " = struct{}{}")
	}
	g.P(structPtr, ".", opaqueOneofFieldName(oneof, message.isOpaque()), " = nil")
	g.P("}")
	g.P()
}

// opaqueGenWhichOneof generates the Which method for each oneof union, as well as the case values for each member
// of that union.
func opaqueGenWhichOneof(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
	// Go through the message, and for each field that is the first of a oneof field, dig down
	// and generate constants + the actual which method.
	oneofIndex := 0
	for _, field := range message.Fields {
		if oneof := field.Oneof; oneof != nil {
			if !isFirstOneofField(field) {
				continue
			}
			caseType := opaqueOneofCaseTypeName(oneof)
			g.P("const ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ", caseType, " = ", 0)
			for _, f := range oneof.Fields {
				g.P("const ", message.GoIdent.GoName, "_", f.GoName, "_case ", caseType, " = ", f.Desc.Number())
			}
			fieldtrackNoInterface(g, message.noInterface)
			whicherName := oneof.MethodName("Which")
			g.P("func (x *", message.GoIdent, ") ", whicherName, "() ", caseType, " {")
			g.P("if x == nil {")
			g.P("return ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ")
			g.P("}")
			g.P("switch x.", opaqueOneofFieldName(oneof, message.isOpaque()), ".(type) {")
			for _, f := range oneof.Fields {
				g.P("case *", opaqueFieldOneofType(f, message.isOpaque()), ":")
				g.P("return ", message.GoIdent.GoName, "_", f.GoName, "_case")
			}
			g.P("default", ":")
			g.P("return ", message.GoIdent.GoName, "_", oneof.GoName, "_not_set_case ")
			g.P("}")
			g.P("}")
			g.P()
			oneofIndex++
		}
	}
}

func opaqueNeedsPresenceArray(message *messageInfo) bool {
	if !message.isOpaque() {
		return false
	}
	for _, field := range message.Fields {
		if opaqueFieldNeedsPresenceArray(message, field) {
			return true
		}
	}
	return false
}

func opaqueNeedsLazyStruct(message *messageInfo) bool {
	for _, field := range message.Fields {
		if isLazy(field) {
			return true
		}
	}
	return false
}

// opaqueGenMessageBuilder generates a Builder type for a message.
func opaqueGenMessageBuilder(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
	if message.isOpen() {
		return
	}
	// Builder type.
	bName := g.QualifiedGoIdent(message.GoIdent) + genid.BuilderSuffix_goname
	g.AnnotateSymbol(message.GoIdent.GoName+genid.BuilderSuffix_goname, protogen.Annotation{Location: message.Location})

	leadingComments := appendDeprecationSuffix("",
		message.Desc.ParentFile(),
		message.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
	g.P(leadingComments, "type ", bName, " struct {")
	g.P("_ [0]func() // Prevents comparability and use of unkeyed literals for the builder.")
	g.P()
	for _, field := range message.Fields {
		oneof := field.Oneof
		if oneof == nil && field.Desc.IsWeak() {
			continue
		}

		goType, pointer := opaqueBuilderFieldGoType(g, f, message, field)
		if pointer {
			goType = "*" + goType
		} else if oneof != nil && fieldDefaultValue(g, f, message, field) != "nil" {
			goType = "*" + goType
		}
		// Track all non-oneof fields. Note: synthetic oneofs are an
		// implementation detail of proto3 optional fields:
		// go/proto-proposals/proto3-presence.md, which should be tracked.
		tag := ""
		if (oneof == nil || oneof.Desc.IsSynthetic()) && message.isTracked {
			tag = "`go:\"track\"`"
		}
		if oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
			if oneof.Comments.Leading != "" {
				g.P(oneof.Comments.Leading)
				g.P()
			}
			g.P("// Fields of oneof ", opaqueOneofFieldName(oneof, message.isOpaque()), ":")
		}
		g.AnnotateSymbol(field.Parent.GoIdent.GoName+genid.BuilderSuffix_goname+"."+field.BuilderFieldName(), protogen.Annotation{Location: field.Location})
		leadingComments := appendDeprecationSuffix(field.Comments.Leading,
			field.Desc.ParentFile(),
			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
		g.P(leadingComments,
			field.BuilderFieldName(), " ", goType, " ", tag)
		if oneof != nil && oneof.Fields[len(oneof.Fields)-1] == field && !oneof.Desc.IsSynthetic() {
			g.P("// -- end of ", opaqueOneofFieldName(oneof, message.isOpaque()))
		}
	}
	g.P("}")
	g.P()

	opaqueGenBuildMethod(g, f, message, bName)
}

// opaqueGenBuildMethod generates the actual Build method for the builder
func opaqueGenBuildMethod(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, bName string) {
	// Build method on the builder type.
	fieldtrackNoInterface(g, message.noInterface)
	g.P("func (b0 ", bName, ") Build() *", message.GoIdent, " {")
	g.P("m0 := &", message.GoIdent, "{}")

	if message.isTracked {
		// Redeclare the builder and message types as local
		// defined types, so that field tracking records the
		// field uses against these types instead of the
		// original struct types.
		//
		// TODO: Actually redeclare the struct types
		// without `go:"track"` tags?
		g.P("type (notrackB ", bName, "; notrackM ", message.GoIdent, ")")
		g.P("b, x := (*notrackB)(&b0), (*notrackM)(m0)")
	} else {
		g.P("b, x := &b0, m0")
	}
	g.P("_, _ = b, x")

	for _, field := range message.Fields {
		oneof := field.Oneof
		if oneof == nil && field.Desc.IsWeak() {
			continue
		}
		if oneof != nil && !oneof.Desc.IsSynthetic() {
			qual := ""
			if fieldDefaultValue(g, f, message, field) != "nil" {
				qual = "*"
			}

			g.P("if b.", field.BuilderFieldName(), " != nil {")
			oneofName := opaqueOneofFieldName(oneof, message.isOpaque())
			oneofType := opaqueFieldOneofType(field, message.isOpaque())
			g.P("x.", oneofName, " = &", oneofType, "{", qual, "b.", field.BuilderFieldName(), "}")
			g.P("}")
		} else { // proto3 optional ends up here (synthetic oneof)
			qual := ""
			_, pointer := opaqueBuilderFieldGoType(g, f, message, field)
			if pointer && message.isOpaque() && !field.Desc.IsList() && field.Desc.Kind() != protoreflect.StringKind {
				qual = "*"
			} else if message.isOpaque() && field.Desc.IsList() && field.Desc.Message() != nil {
				qual = "&"
			}
			presence := usePresence(message, field)
			if presence {
				g.P("if b.", field.BuilderFieldName(), " != nil {")
			}
			if presence {
				pi := opaqueFieldPresenceIndex(field)
				g.P(protoimplPackage.Ident("X"), ".SetPresentNonAtomic(&(x.XXX_presence[", pi/32, "]),", pi, ",", opaqueNumPresenceFields(message), ")")
			}
			goName := field.GoName
			if message.isOpaque() {
				goName = "xxx_hidden_" + goName
			}
			g.P("x.", goName, " = ", qual, "b.", field.BuilderFieldName())
			if presence {
				g.P("}")
			}
		}
	}

	g.P("return m0")
	g.P("}")
	g.P()
}

// opaqueBuilderFieldGoType does the same as opaqueFieldGoType, but corrects for
// types that are different in a builder
func opaqueBuilderFieldGoType(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) (goType string, pointer bool) {
	goType, pointer = opaqueFieldGoType(g, f, message, field)
	kind := field.Desc.Kind()

	// Use []T instead of *[]T for opaque repeated lists.
	if message.isOpaque() && field.Desc.IsList() {
		pointer = false
	}

	// Use *T for optional fields.
	optional := field.Desc.HasPresence()
	if optional &&
		kind != protoreflect.GroupKind &&
		kind != protoreflect.MessageKind &&
		kind != protoreflect.BytesKind &&
		field.Desc.Cardinality() != protoreflect.Repeated {
		pointer = true
	}

	return goType, pointer
}

func opaqueGenOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo) {
	// TODO: We should avoid generating these wrapper types in pure-opaque mode.
	if !message.isOpen() {
		for _, oneof := range message.Oneofs {
			if oneof.Desc.IsSynthetic() {
				continue
			}
			caseTypeName := opaqueOneofCaseTypeName(oneof)
			g.P("type ", caseTypeName, " ", protoreflectPackage.Ident("FieldNumber"))
			g.P("")

			idx := f.allMessagesByPtr[message]
			typesVar := messageTypesVarName(f)
			g.P("func (x ", caseTypeName, ") String() string {")
			g.P("md := ", typesVar, "[", idx, "].Descriptor()")
			g.P("if x == 0 {")
			g.P(`return "not set"`)
			g.P("}")
			g.P("return ", protoimplPackage.Ident("X"), ".MessageFieldStringOf(md, ", protoreflectPackage.Ident("FieldNumber"), "(x))")
			g.P("}")
			g.P()
		}
	}
	for _, oneof := range message.Oneofs {
		if oneof.Desc.IsSynthetic() {
			continue
		}
		ifName := opaqueOneofInterfaceName(oneof)
		g.P("type ", ifName, " interface {")
		g.P(ifName, "()")
		g.P("}")
		g.P()
		for _, field := range oneof.Fields {
			name := opaqueFieldOneofType(field, message.isOpaque())
			g.AnnotateSymbol(name.GoName, protogen.Annotation{Location: field.Location})
			g.AnnotateSymbol(name.GoName+"."+field.GoName, protogen.Annotation{Location: field.Location})
			g.P("type ", name, " struct {")
			goType, _ := opaqueFieldGoType(g, f, message, field)
			protobufTagValue := fieldProtobufTagValue(field)
			if g.InternalStripForEditionsDiff() {
				protobufTagValue = strings.ReplaceAll(protobufTagValue, ",proto3", "")
			}
			tags := structTags{
				{"protobuf", protobufTagValue},
			}
			leadingComments := appendDeprecationSuffix(field.Comments.Leading,
				field.Desc.ParentFile(),
				field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
			g.P(leadingComments,
				field.GoName, " ", goType, tags,
				trailingComment(field.Comments.Trailing))
			g.P("}")
			g.P()
		}
		for _, field := range oneof.Fields {
			g.P("func (*", opaqueFieldOneofType(field, message.isOpaque()), ") ", ifName, "() {}")
			g.P()
		}
	}
}

// opaqueFieldGoType returns the Go type used for a field.
//
// If it returns pointer=true, the struct field is a pointer to the type.
func opaqueFieldGoType(g *protogen.GeneratedFile, f *fileInfo, message *messageInfo, field *protogen.Field) (goType string, pointer bool) {
	if field.Desc.IsWeak() {
		return "struct{}", false
	}

	pointer = true
	switch field.Desc.Kind() {
	case protoreflect.BoolKind:
		goType = "bool"
	case protoreflect.EnumKind:
		goType = g.QualifiedGoIdent(field.Enum.GoIdent)
	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
		goType = "int32"
	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
		goType = "uint32"
	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
		goType = "int64"
	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
		goType = "uint64"
	case protoreflect.FloatKind:
		goType = "float32"
	case protoreflect.DoubleKind:
		goType = "float64"
	case protoreflect.StringKind:
		goType = "string"
	case protoreflect.BytesKind:
		goType = "[]byte"
		pointer = false
	case protoreflect.MessageKind, protoreflect.GroupKind:
		goType = opaqueMessageFieldGoType(g, f, field, message.isOpaque())
		pointer = false
	}
	switch {
	case field.Desc.IsList():
		goType = "[]" + goType
		pointer = false
	case field.Desc.IsMap():
		keyType, _ := opaqueFieldGoType(g, f, message, field.Message.Fields[0])
		valType, _ := opaqueFieldGoType(g, f, message, field.Message.Fields[1])
		return fmt.Sprintf("map[%v]%v", keyType, valType), false
	}

	// Extension fields always have pointer type, even when defined in a proto3 file.
	if !field.Desc.IsExtension() && !field.Desc.HasPresence() {
		pointer = false
	}

	if message.isOpaque() {
		switch {
		case field.Desc.IsList() && field.Desc.Message() != nil:
			pointer = true
		case !field.Desc.IsList() && field.Desc.Kind() == protoreflect.StringKind:
			switch {
			case field.Desc.HasPresence():
				pointer = true
			default:
				pointer = false
			}
		default:
			pointer = false
		}
	}

	return goType, pointer
}

func opaqueMessageFieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field, isOpaque bool) string {
	return "*" + g.QualifiedGoIdent(field.Message.GoIdent)
}

// opaqueFieldPresenceIndex returns the index to pass to presence functions.
//
// TODO: field.Desc.Index() would be simpler, and would give space to record the presence of oneof fields.
func opaqueFieldPresenceIndex(field *protogen.Field) int {
	structFieldIndex := 0
	for _, f := range field.Parent.Fields {
		if field == f {
			break
		}
		if f.Oneof == nil || isLastOneofField(f) {
			structFieldIndex++
		}
	}
	return structFieldIndex
}

// opaqueNumPresenceFields returns the number of fields that may be passed to presence functions.
//
// Since all fields in a oneof currently share a single entry in the presence bitmap,
// this is not just len(message.Fields).
func opaqueNumPresenceFields(message *messageInfo) int {
	if len(message.Fields) == 0 {
		return 0
	}
	return opaqueFieldPresenceIndex(message.Fields[len(message.Fields)-1]) + 1
}

func fieldtrackNoInterface(g *protogen.GeneratedFile, isTracked bool) {
	if isTracked {
		g.P("//go:nointerface")
	}
}

// opaqueOneofFieldName returns the name of the struct field that holds
// the value of a oneof.
func opaqueOneofFieldName(oneof *protogen.Oneof, isOpaque bool) string {
	if isOpaque {
		return "xxx_hidden_" + oneof.GoName
	}
	return oneof.GoName
}

func opaqueFieldOneofType(field *protogen.Field, isOpaque bool) protogen.GoIdent {
	ident := protogen.GoIdent{
		GoImportPath: field.Parent.GoIdent.GoImportPath,
		GoName:       field.Parent.GoIdent.GoName + "_" + field.GoName,
	}
	// Check for collisions with nested messages or enums.
	//
	// This conflict resolution is incomplete: Among other things, it
	// does not consider collisions with other oneof field types.
Loop:
	for {
		for _, message := range field.Parent.Messages {
			if message.GoIdent == ident {
				ident.GoName += "_"
				continue Loop
			}
		}
		for _, enum := range field.Parent.Enums {
			if enum.GoIdent == ident {
				ident.GoName += "_"
				continue Loop
			}
		}
		return unexportIdent(ident, isOpaque)
	}
}

// unexportIdent turns id into its unexported version (by lower-casing), but
// only if isOpaque is set. This function is used for oneof wrapper types,
// which remain exported in the non-opaque API for now.
func unexportIdent(id protogen.GoIdent, isOpaque bool) protogen.GoIdent {
	if !isOpaque {
		return id
	}
	r, sz := utf8.DecodeRuneInString(id.GoName)
	if r == utf8.RuneError {
		panic(fmt.Sprintf("Go identifier %q contains invalid UTF8?!", id.GoName))
	}
	r = unicode.ToLower(r)
	id.GoName = string(r) + id.GoName[sz:]
	return id
}

func opaqueOneofInterfaceName(oneof *protogen.Oneof) string {
	return fmt.Sprintf("is%s_%s", oneof.Parent.GoIdent.GoName, oneof.GoName)
}
func opaqueOneofCaseTypeName(oneof *protogen.Oneof) string {
	return fmt.Sprintf("case_%s_%s", oneof.Parent.GoIdent.GoName, oneof.GoName)
}

// isFirstOneofField reports whether this is the first field in a oneof.
func isFirstOneofField(field *protogen.Field) bool {
	return field.Oneof != nil && field == field.Oneof.Fields[0] && !field.Oneof.Desc.IsSynthetic()
}

// isLastOneofField returns true if this is the last field in a oneof.
func isLastOneofField(field *protogen.Field) bool {
	return field.Oneof != nil && field == field.Oneof.Fields[len(field.Oneof.Fields)-1]
}
