summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-17 09:41:52 -0500
committerJeff Carr <[email protected]>2025-10-17 09:41:52 -0500
commit367f681a490a48944c5d05ba0fe89d0099c0337d (patch)
treebdd3c500f740588cf6aaf790f13e2ebad37bc88d
parent4d86a4cc8e308d9f7d9526dd1fe55011d6c8d96c (diff)
move stuff here from lib/configv0.0.8
-rw-r--r--Makefile3
-rw-r--r--fakefile.disabled10
-rw-r--r--fakefile.go159
-rw-r--r--identify.go4
-rw-r--r--lookupPB.go165
-rw-r--r--mockProto.go44
6 files changed, 383 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index aa6482e..1f704e3 100644
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,9 @@ generate: clean
go mod tidy
go generate
+raw-protoc:
+ cd ~/go/src && protoc --go_out=. --proto_path=go.wit.com/lib/protobuf/filepb --go_opt=Mfakefile.proto=go.wit.com/lib/protobuf/filepb fakefile.proto
+
go-generate:
rm -f *.pb.go *.patch
diff --git a/fakefile.disabled b/fakefile.disabled
new file mode 100644
index 0000000..72a06d9
--- /dev/null
+++ b/fakefile.disabled
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+// name changed so automated .proto tools don't see it
+
+package filepb;
+
+message FakeFile {
+ string uuid = 1; // `autogenpb:uuid:`
+ string version = 2; // `autogenpb:version:`
+}
diff --git a/fakefile.go b/fakefile.go
new file mode 100644
index 0000000..1400eb9
--- /dev/null
+++ b/fakefile.go
@@ -0,0 +1,159 @@
+// kept here to use for identifying .pb files using autogenpb
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.33.0
+// protoc v3.21.12
+// source: fakefile.proto
+
+package filepb
+
+import (
+ reflect "reflect"
+ sync "sync"
+
+ "google.golang.org/protobuf/proto"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type FakeFile struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // `autogenpb:uuid:`
+ Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:`
+}
+
+// unmarshal from wire. You have won.
+func (v *FakeFile) Unmarshal(data []byte) error {
+ return proto.Unmarshal(data, v)
+}
+
+func (x *FakeFile) Reset() {
+ *x = FakeFile{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_fakefile_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FakeFile) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FakeFile) ProtoMessage() {}
+
+func (x *FakeFile) ProtoReflect() protoreflect.Message {
+ mi := &file_fakefile_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FakeFile.ProtoReflect.Descriptor instead.
+func (*FakeFile) Descriptor() ([]byte, []int) {
+ return file_fakefile_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *FakeFile) GetUuid() string {
+ if x != nil {
+ return x.Uuid
+ }
+ return ""
+}
+
+func (x *FakeFile) GetVersion() string {
+ if x != nil {
+ return x.Version
+ }
+ return ""
+}
+
+var File_fakefile_proto protoreflect.FileDescriptor
+
+var file_fakefile_proto_rawDesc = []byte{
+ 0x0a, 0x0e, 0x66, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x06, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x62, 0x22, 0x38, 0x0a, 0x08, 0x46, 0x61, 0x6b, 0x65,
+ 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_fakefile_proto_rawDescOnce sync.Once
+ file_fakefile_proto_rawDescData = file_fakefile_proto_rawDesc
+)
+
+func file_fakefile_proto_rawDescGZIP() []byte {
+ file_fakefile_proto_rawDescOnce.Do(func() {
+ file_fakefile_proto_rawDescData = protoimpl.X.CompressGZIP(file_fakefile_proto_rawDescData)
+ })
+ return file_fakefile_proto_rawDescData
+}
+
+var file_fakefile_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_fakefile_proto_goTypes = []interface{}{
+ (*FakeFile)(nil), // 0: filepb.FakeFile
+}
+var file_fakefile_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_fakefile_proto_init() }
+func file_fakefile_proto_init() {
+ if File_fakefile_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_fakefile_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FakeFile); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_fakefile_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_fakefile_proto_goTypes,
+ DependencyIndexes: file_fakefile_proto_depIdxs,
+ MessageInfos: file_fakefile_proto_msgTypes,
+ }.Build()
+ File_fakefile_proto = out.File
+ file_fakefile_proto_rawDesc = nil
+ file_fakefile_proto_goTypes = nil
+ file_fakefile_proto_depIdxs = nil
+}
diff --git a/identify.go b/identify.go
index 618e34c..0de53a2 100644
--- a/identify.go
+++ b/identify.go
@@ -12,8 +12,8 @@ func IdentifyPB(filename string) (string, string, error) {
return "", "", err
}
- var pb *Identify
- pb = new(Identify)
+ var pb *FakeFile
+ pb = new(FakeFile)
if err := pb.Unmarshal(data); err != nil {
return "", "", err
}
diff --git a/lookupPB.go b/lookupPB.go
new file mode 100644
index 0000000..531e0d2
--- /dev/null
+++ b/lookupPB.go
@@ -0,0 +1,165 @@
+package filepb
+
+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)
+ }
+ }
+ }
+}
diff --git a/mockProto.go b/mockProto.go
new file mode 100644
index 0000000..1b104c3
--- /dev/null
+++ b/mockProto.go
@@ -0,0 +1,44 @@
+package filepb
+
+import (
+ "google.golang.org/protobuf/encoding/prototext"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+// --- Mock of a generated user.pb.go file ---
+type PatchError struct {
+ // Note: The `XXX_` fields are part of the older struct tags,
+ // but the reflection logic comes from the modern API.
+ // In a real generated file, you wouldn't see these tags.
+ UserName string `protobuf:"bytes,1,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"`
+ UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
+ Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
+ LastLogin *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=last_login,json=lastLogin,proto3" json:"last_login,omitempty"`
+}
+
+func (x *PatchError) Reset() { *x = PatchError{} }
+func (x *PatchError) String() string { return prototext.Format(x) } // Modern way to implement String()
+func (*PatchError) ProtoMessage() {}
+
+// In a real generated file, ProtoReflect() would be fully implemented.
+// For this example, we don't need it as the marshallers will use reflection.
+func (x *PatchError) ProtoReflect() protoreflect.Message { return nil }
+
+// --- End of mock ---
+
+/*
+ user := &User{
+ UserName:"jdoe",
+ UserId: 12345,
+ Email: "[email protected]",
+ LastLogin: timestamppb.Now(),
+ }
+
+ fmt.Println"==========================================================")
+ fmt.Println"1. The Best Method: prototext.Format (like spew.Dump)")
+ fmt.Println"==========================================================")
+// The prototext.Format function is the most direct equivalent.
+ outText := prototext.Format(user)
+ fmt.Println(outText)
+*/