package decodebudget
import (
"reflect"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/dynamicpb"
)
type messageLayout struct {
generated bool
size int
}
func layoutOf(desc protoreflect.MessageDescriptor) messageLayout {
return infoOf(desc).layout
}
func newLayout(desc protoreflect.MessageDescriptor) messageLayout {
l := messageLayout{size: 64 + 32*desc.Fields().Len()}
if mt, err := protoregistry.GlobalTypes.FindMessageByName(desc.FullName()); err == nil {
if t := reflect.TypeOf(mt.Zero().Interface()); t != reflect.TypeFor[*dynamicpb.Message]() && t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Struct {
l.generated = true
l.size = int(t.Elem().Size())
}
}
l.size = allocSize(l.size)
return l
}
func protoStructSize(desc protoreflect.MessageDescriptor) int {
return layoutOf(desc).size
}
func goValueSize(field protoreflect.FieldDescriptor) int {
switch field.Kind() {
case protoreflect.BoolKind:
return 1
case protoreflect.EnumKind, protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind,
protoreflect.FloatKind, protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind:
return 4
case protoreflect.StringKind:
return 16
case protoreflect.BytesKind:
return 24
default:
return 8
}
}
func hasPointers(field protoreflect.FieldDescriptor) bool {
switch field.Kind() {
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
return true
}
return false
}