status-go/_assets/generate_handlers/generate_handlers.go

130 lines
2.9 KiB
Go

//go:generate go run generate_handlers.go
package main
import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
"text/template"
)
// EnumType defines the type of the protobuf enum
type EnumType struct {
Name string
Values []string
}
// MethodInfo holds information about a method
type MethodInfo struct {
ProtobufName string
MethodName string
EnumValue string
ProcessRaw bool
SyncMessage bool
FromArchiveArg bool
}
func main() {
inputFile := "../../protocol/protobuf/application_metadata_message.proto"
outputFile := "../../protocol/messenger_handlers.go"
templateFile := "./generate_handlers_template.txt"
enumName := "Type"
// Load the protobuf file
content, err := ioutil.ReadFile(inputFile)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
templateFileContent, err := os.ReadFile(templateFile)
if err != nil {
fmt.Println("Failed to read template:", err)
os.Exit(1)
}
// Extract enum values
enum := extractEnum(content, enumName)
// Prepare method information
var methodInfos []MethodInfo
for _, value := range enum.Values {
protobufName := toCamelCase(value)
if protobufName == "Unknown" || strings.HasPrefix(value, "DEPRECATED") {
continue
}
methodName := "handle" + protobufName + "Protobuf"
info := MethodInfo{MethodName: methodName, ProtobufName: protobufName, EnumValue: value}
if strings.HasPrefix(value, "SYNC_") {
info.SyncMessage = true
}
if protobufName == "PushNotificationRegistration" {
info.ProcessRaw = true
}
info.FromArchiveArg = protobufName == "ChatMessage" || protobufName == "PinMessage"
methodInfos = append(methodInfos, info)
}
// Generate code
templateCode := string(templateFileContent)
tmpl, err := template.New("handlers").Parse(templateCode)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
output, err := os.Create(outputFile)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
defer output.Close()
err = tmpl.Execute(output, methodInfos)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
fmt.Printf("Generated handlers in %s for %s enum.\n", outputFile, enumName)
}
func extractEnum(content []byte, enumName string) EnumType {
enumPattern := fmt.Sprintf(`enum\s+%s\s*{([^}]+)}`, enumName)
re := regexp.MustCompile(enumPattern)
match := re.FindStringSubmatch(string(content))
if len(match) != 2 {
fmt.Println("Enum not found")
os.Exit(1)
}
valuesPattern := `(?m)^\s*([A-Z_0-9]+)\s*=\s*\d+;`
re = regexp.MustCompile(valuesPattern)
valueMatches := re.FindAllStringSubmatch(match[1], -1)
values := make([]string, len(valueMatches))
for i, match := range valueMatches {
values[i] = strings.TrimSpace(match[1])
}
return EnumType{Name: enumName, Values: values}
}
func toCamelCase(s string) string {
words := strings.Split(strings.ToLower(s), "_")
for i, word := range words {
words[i] = strings.Title(word)
}
return strings.Join(words, "")
}