summaryrefslogtreecommitdiff
path: root/lookupPB.go
diff options
context:
space:
mode:
Diffstat (limited to 'lookupPB.go')
-rw-r--r--lookupPB.go165
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)
+ }
+ }
+ }
+}