package config import ( "fmt" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" ) // Gemini AI can help author some pretty good protobuf code. // I never remember the syntax for 'reflect' on these things. // this will try both "filename" and "Filename" func GetFilename(pb proto.Message) (string, error) { // 1. Get the protoreflect.Message interface from the message. // This is the entry point to the reflection API. msg := pb.ProtoReflect() // 2. Get the message's descriptor, which contains metadata about its fields. descriptor := msg.Descriptor() // 3. Find the specific field descriptor by its protobuf name ("Filename"). // Note: The field name must match the name in the .proto file. fieldName := protoreflect.Name("Filename") fieldDescriptor := descriptor.Fields().ByName(fieldName) // try upper case if fieldDescriptor == nil { fieldName = protoreflect.Name("filename") fieldDescriptor = descriptor.Fields().ByName(fieldName) // if fieldDescriptor == nil { // panic(".proto file: try 'Filename', not 'filename'? or maybe nomutex if pb.Marshal() fails") // } } // 4. Check if the field was found. If not, return false. if fieldDescriptor == nil { return "", fmt.Errorf("fieldDescriptor == nil") } // 5. (Optional but recommended) Verify the field is a string type. if fieldDescriptor.Kind() != protoreflect.StringKind { // The field exists but is not a string, so we can't return it as one. return "", fmt.Errorf("The field exists but is not a string") } // 6. If the field exists and is a string, get its value. // The value is returned as a protoreflect.Value. value := msg.Get(fieldDescriptor) // 7. Convert the protoreflect.Value to a native Go string. return value.String(), nil } // sets "Filename" if it exists in the protobuf func SetFilename(pb proto.Message, filename string) (bool, error) { msg := pb.ProtoReflect() // This is the entry point to the reflection API. descriptor := msg.Descriptor() // Get the message's descriptor, which contains metadata about its fields. fieldName := protoreflect.Name("Filename") fieldDescriptor := descriptor.Fields().ByName(fieldName) if fieldDescriptor == nil { fieldName = protoreflect.Name("filename") fieldDescriptor = descriptor.Fields().ByName(fieldName) } if fieldDescriptor == nil { return false, fmt.Errorf("fieldDescriptor == nil") } if fieldDescriptor.Kind() != protoreflect.StringKind { // The field exists but is not a string, so we can't return it as one. return false, fmt.Errorf("The field exists but is not a string") } valueToSet := protoreflect.ValueOfString(filename) // 6. If the field exists and is a string, get its value. // The value is returned as a protoreflect.Value. msg.Set(fieldDescriptor, valueToSet) // 7. Convert the protoreflect.Value to a native Go string. return true, nil }