golang / protobuf

Go support for Google's protocol buffers
BSD 3-Clause "New" or "Revised" License
9.64k stars 1.58k forks source link

How to cast descriptorpb.DescriptorProto to protoreflect.MessageDescriptor #1590

Closed Eagleye126 closed 5 months ago

Eagleye126 commented 5 months ago

Hey all, Im trying to create *dynamicpb.Message the following way:

import (
    "github.com/stretchr/testify/assert"
    "google.golang.org/protobuf/proto"
    "google.golang.org/protobuf/reflect/protoreflect"
    "google.golang.org/protobuf/types/descriptorpb"
    "google.golang.org/protobuf/types/dynamicpb"
    "testing"
)

func getDescriptorProto(fieldName string) protoreflect.MessageDescriptor {
    descProto := descriptorpb.DescriptorProto{
        Field: []*descriptorpb.FieldDescriptorProto{
            {
                Name: proto.String(fieldName),
                Type: descriptorpb.FieldDescriptorProto_TYPE_INT32.Enum(),
            },
        },
    }
    return descProto.ProtoReflect().Descriptor()
}

func getDynamicMessage(descriptor protoreflect.MessageDescriptor, value int32) *dynamicpb.Message {
    dynamicMessage := dynamicpb.NewMessage(descriptor)
    dynamicMessage.Set(dynamicMessage.Descriptor().Fields().ByName("id"), protoreflect.ValueOf(value))
    return dynamicMessage
}

var (
    idDescriptorProto = getDescriptorProto("id")
)

var (
    validIdMessage = getDynamicMessage(idDescriptorProto, int32(2))
)

Im getting this panic error: runtime error: invalid memory address or nil pointer dereference

Seems like it triggers from dynamicMessage.Descriptor().Fields().ByName(... And thats because descProto.ProtoReflect().Descriptor() will return the object without the fields I set.

Thank you for helping!

neild commented 5 months ago
descProto := descriptorpb.DescriptorProto{...}
return descProto.ProtoReflect().Descriptor()

This returns the descriptor of descProto, not the descriptor in descProto.

That is, it returns the descriptor for google.protobuf.DescriptorProto, which does not contain an id field.

You can use the google.golang.org/protobuf/reflect/protodesc package to convert a DescriptorProto to a protoreflect.MessageDescriptor.

lfolger commented 5 months ago

Closing for now. Please reopen the issue if you have further questions.