summaryrefslogtreecommitdiff
path: root/autogenpbName.go
blob: f2e492c9b4a94d8bed494411b14d93775100d8bc (plain)
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
package config

import (
	"fmt"

	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
)

// Because you followed autogenpb's advice (you did follow it right?) you now
// win the automation lottery.
//
// for this .proto file, GetProtobufName(pb) returns "repos"
// Then, ConfigLoad(), ConfigSave(), CacheLoad() and CacheSave()
// all do exactly what is expected:
//
// Automatically work with the files:
//
//	~/.config/<appname>/repos.pb
//
// or
//
//	~/.cache/<appname/repos.pb
//
//	message Repos {
//	        string                      uuid                     = 1;
//	        string                      version                  = 2;
//	        repeated Repo               repos                    = 3;
func GetProtobufName(pb proto.Message) (string, error) {
	// 1. Get the protoreflect.Message interface.
	msg := pb.ProtoReflect()

	// 2. Get the message's descriptor.
	descriptor := msg.Descriptor()

	// 3. Get all the field descriptors for the message.
	fields := descriptor.Fields()

	// find string "uuid"
	fieldNumber := protoreflect.FieldNumber(1)
	fieldDescriptor := fields.ByNumber(fieldNumber)

	if fieldDescriptor == nil {
		return "", fmt.Errorf("message %q has no field with number 1", descriptor.FullName())
	}
	if fieldDescriptor.Name() != "uuid" {
		return "", fmt.Errorf("message %q field(1) != 'uuid' is (%s)", descriptor.FullName(), fieldDescriptor.Name())
	}

	// find string "version"
	fieldNumber = protoreflect.FieldNumber(2)
	fieldDescriptor = fields.ByNumber(fieldNumber)

	if fieldDescriptor == nil {
		return "", fmt.Errorf("message %q has no field(2)", descriptor.FullName())
	}
	if fieldDescriptor.Name() != "version" {
		return "", fmt.Errorf("message %q field(2) != 'version' is (%s)", descriptor.FullName(), fieldDescriptor.Name())
	}

	// 4. Find the field descriptor specifically by its number (3).
	// This is the crucial step.
	fieldNumber = protoreflect.FieldNumber(3)
	fieldDescriptor = fields.ByNumber(fieldNumber)

	// 5. Add some safety checks.
	if fieldDescriptor == nil {
		return "", fmt.Errorf("message %q has no field with number 3", descriptor.FullName())
	}

	// Optional but recommended: verify it's a repeated field as you expect.
	// IsList() is the reflection equivalent of `repeated`.
	if !fieldDescriptor.IsList() {
		return "", fmt.Errorf("field with number 3 (%q) is not a repeated field", fieldDescriptor.Name())
	}

	// 6. Get the name from the descriptor and return it.
	// The name is of type protoreflect.Name, so we cast it to a string.
	return string(fieldDescriptor.Name()), nil
}

func GetThirdFieldName(pb proto.Message) (string, error) {
	// 1. Get the protoreflect.Message interface.
	msg := pb.ProtoReflect()

	// 2. Get the message's descriptor.
	descriptor := msg.Descriptor()

	// 3. Get all the field descriptors for the message.
	fields := descriptor.Fields()

	// 4. Find the field descriptor specifically by its number (3).
	// This is the crucial step.
	fieldNumber := protoreflect.FieldNumber(3)
	fieldDescriptor := fields.ByNumber(fieldNumber)

	// 5. Add some safety checks.
	if fieldDescriptor == nil {
		return "", fmt.Errorf("message %q has no field with number 3", descriptor.FullName())
	}

	// Optional but recommended: verify it's a repeated field as you expect.
	// IsList() is the reflection equivalent of `repeated`.
	if !fieldDescriptor.IsList() {
		return "", fmt.Errorf("field with number 3 (%q) is not a repeated field", fieldDescriptor.Name())
	}

	// 6. Get the name from the descriptor and return it.
	// The name is of type protoreflect.Name, so we cast it to a string.
	return string(fieldDescriptor.Name()), nil
}