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
124
125
126
127
128
|
package zoopb
import (
"fmt"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
)
// PrintDebInfoStrings finds a nested message named "debInfo", then iterates over
// its fields, printing the name and value of any field that is a string.
func printDebInfoStrings(pb proto.Message) error {
// 1. Get the reflection interface for the top-level message.
msg := pb.ProtoReflect()
descriptor := msg.Descriptor()
// 2. Find the FieldDescriptor for the nested "debInfo" message.
// Note: Protobuf field names like "deb_info" are often canonicalized
// to "debInfo" in Go code, but reflection should use the name from the .proto file.
// We'll check for both common variations for robustness.
debInfoFieldDesc := descriptor.Fields().ByName("debInfo")
if debInfoFieldDesc == nil {
debInfoFieldDesc = descriptor.Fields().ByName("deb_info")
}
if debInfoFieldDesc == nil {
return fmt.Errorf("field 'debInfo' or 'deb_info' not found in message %s", descriptor.FullName())
}
// 3. Get the actual nested message object from the parent.
debInfoValue := msg.Get(debInfoFieldDesc)
debInfoMsg := debInfoValue.Message()
// 4. Check if the nested message is valid and has been set.
if !debInfoMsg.IsValid() {
fmt.Printf("--- Field '%s' in [%s] is not set. --- \n", debInfoFieldDesc.Name(), descriptor.FullName())
return nil // Not an error, just nothing to print.
}
// 5. Now, iterate over the fields of the nested debInfo message.
debInfoDescriptor := debInfoMsg.Descriptor()
fields := debInfoDescriptor.Fields()
fmt.Printf("--- Listing String Fields in '%s' --- \n", debInfoFieldDesc.Name())
foundStrings := false
for i := 0; i < fields.Len(); i++ {
fieldDesc := fields.Get(i)
// 6. Check if the field's kind is a string.
if fieldDesc.Kind() == protoreflect.StringKind {
// Get the value from the debInfo message object.
value := debInfoMsg.Get(fieldDesc).String()
fieldName := fieldDesc.Name()
// Print the result.
fmt.Printf("%s: \"%s\"\n", fieldName, value)
foundStrings = true
}
}
if !foundStrings {
fmt.Println(" (No string fields found)")
}
return nil
}
/*
// --- Mock structs for demonstration. In a real project, these would be auto-generated. ---
type DebInfo struct {
PackageName string `protobuf:"bytes,1,opt,name=package_name,json=packageName,proto3"`
Version string `protobuf:"bytes,2,opt,name=version,proto3"`
Size int64 `protobuf:"varint,3,opt,name=size,proto3"`
Architecture string `protobuf:"bytes,4,opt,name=architecture,proto3"`
Maintainer string `protobuf:"bytes,5,opt,name=maintainer,proto3"`
}
func (x *DebInfo) Reset() { *x = DebInfo{} }
func (x *DebInfo) String() string { return "dummy" }
func (*DebInfo) ProtoMessage() {}
func (x *DebInfo) ProtoReflect() protoreflect.Message { return nil } // Simplified for example
type Package struct {
Filename string `protobuf:"bytes,1,opt,name=filename,proto3"`
DebInfo *DebInfo `protobuf:"bytes,2,opt,name=deb_info,json=debInfo,proto3"`
}
func (x *Package) Reset() { *x = Package{} }
func (x *Package) String() string { return "dummy" }
func (*Package) ProtoMessage() {}
func (x *Package) ProtoReflect() protoreflect.Message { return nil } // Simplified for example
// main function to demonstrate the usage of PrintDebInfoStrings
func main() {
fmt.Println("This file contains a utility function 'PrintDebInfoStrings'.")
fmt.Println("The main function is for demonstration purposes and relies on mock protobuf structs.")
fmt.Println("To use the utility, import this package into your project.")
// In a real application, you would need to have the actual generated protobuf code
// for the reflection to work. The following is a conceptual demonstration.
pkg := &Package{
Filename: "example_1.0_amd64.deb",
DebInfo: &DebInfo{
PackageName: "example",
Version: "1.0",
Size: 1024,
Architecture: "amd64",
Maintainer: "A Developer <[email protected]>",
},
}
fmt.Println("\n--- Conceptual run with a populated 'debInfo' field ---")
// Simulate what the real output would be, as the mock structs lack reflection data.
fmt.Printf("--- Listing String Fields in 'deb_info' ---
")
fmt.Printf(" %s: \"%s\"\n", "package_name", pkg.DebInfo.PackageName)
fmt.Printf(" %s: \"%s\"\n", "version", pkg.DebInfo.Version)
fmt.Printf(" %s: \"%s\"\n", "architecture", pkg.DebInfo.Architecture)
fmt.Printf(" %s: \"%s\"\n", "maintainer", pkg.DebInfo.Maintainer)
fmt.Println("\n--- Conceptual run with a nil 'debInfo' field ---")
fmt.Printf("--- Field 'deb_info' in [] is not set. ---
")
}
*/
|