diff options
| author | Jeff Carr <[email protected]> | 2025-10-17 09:41:52 -0500 | 
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-10-17 09:41:52 -0500 | 
| commit | 367f681a490a48944c5d05ba0fe89d0099c0337d (patch) | |
| tree | bdd3c500f740588cf6aaf790f13e2ebad37bc88d | |
| parent | 4d86a4cc8e308d9f7d9526dd1fe55011d6c8d96c (diff) | |
move stuff here from lib/configv0.0.8
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | fakefile.disabled | 10 | ||||
| -rw-r--r-- | fakefile.go | 159 | ||||
| -rw-r--r-- | identify.go | 4 | ||||
| -rw-r--r-- | lookupPB.go | 165 | ||||
| -rw-r--r-- | mockProto.go | 44 | 
6 files changed, 383 insertions, 2 deletions
@@ -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) +*/  | 
