diff options
Diffstat (limited to 'lookupPB.go')
| -rw-r--r-- | lookupPB.go | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lookupPB.go b/lookupPB.go new file mode 100644 index 0000000..9fb73a2 --- /dev/null +++ b/lookupPB.go @@ -0,0 +1,165 @@ +package config + +import ( + "errors" + "fmt" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" +) + +var ErrProtoNoVarName error = errors.New("name not in .proto") +var ErrProtoVarNotString error = errors.New("name exists but is not a string") + +// Gemini AI can help author some pretty good protobuf code. +// I never remember the syntax for 'reflect' on these things. + +// 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 +} + +// 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 "", ErrProtoNoVarName + } + + // 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 "", ErrProtoVarNotString + } + + // 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 +} + +// this will try both "filename" and "Filename" +func GetString(pb proto.Message, varname string) (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(varname) + fieldDescriptor := descriptor.Fields().ByName(fieldName) + + // 4. Check if the field was found. If not, return false. + if fieldDescriptor == nil { + return "", ErrProtoNoVarName + } + + // 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 "", ErrProtoVarNotString + } + + // 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 +} + +// don't do this. use prototext.Format(pb) +// duh. I'm dumb. I literally wasted my time + was being lazy so I +// just asked asking Gemini AI to make some function for this +// when, for years, I use prototext.Format() all over the place +func printStrings(pb proto.Message) { + // 1. Get the protoreflect.Message interface. + msg := pb.ProtoReflect() + + // It's good practice to check if the message is valid. + if !msg.IsValid() { + fmt.Printf("Error: Provided protobuf message is not valid.") + return + } + + // 2. Get the message's descriptor. + descriptor := msg.Descriptor() + fmt.Printf("--- Listing String Fields in [%s] ---\n", descriptor.FullName()) + + // 3. Get the collection of all field descriptors for this message. + fields := descriptor.Fields() + + // 4. Iterate over all the fields. + for i := 0; i < fields.Len(); i++ { + // Get the descriptor for the field at the current index. + fieldDescriptor := fields.Get(i) + + // 5. Check if the field's kind is a string. + if fieldDescriptor.Kind() == protoreflect.StringKind { + // 6. If it is a string, get its name and value. + fieldName := fieldDescriptor.Name() + value := msg.Get(fieldDescriptor).String() + + // 7. Print the formatted result. + // We add a check to see if the field is populated. An empty string + // is a valid value, but you might only want to see set fields. + if msg.Has(fieldDescriptor) { + fmt.Printf(" %s: \"%s\"\n", fieldName, value) + } + } + } +} |
