1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
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
}
|