autogenpb/protoParse.go

230 lines
5.7 KiB
Go
Raw Normal View History

package main
// auto run protoc with the correct args
import (
2025-01-09 15:03:05 -06:00
"bufio"
"fmt"
"os"
"strings"
"go.wit.com/log"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
2025-01-08 20:30:33 -06:00
// this parses the .proto file and handles anything with `autogenpb: `
2025-01-09 15:03:05 -06:00
// does the fruit.proto file have "message Fruits"
func (pb *Files) hasPluralMessage(f *File) error {
file, err := os.Open(f.Filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
base := cases.Title(language.English, cases.NoLower).String(f.Filebase)
2025-01-09 15:29:27 -06:00
prefix := "message " + base + "s {" // to conform, it must have an added 's'
2025-01-09 15:03:05 -06:00
if !strings.HasPrefix(line, prefix) {
// log.Info("nope", prefix, "line", line)
// nope, not this line
continue
}
scanner.Scan()
2025-01-09 15:03:05 -06:00
line = scanner.Text()
fields := strings.Fields(line)
// log.Info("GOT LINE", line)
2025-01-09 15:03:05 -06:00
if fields[0] == "string" && fields[1] != "uuid" {
2025-01-12 06:13:42 -06:00
f.noUuid()
2025-01-09 15:03:05 -06:00
return fmt.Errorf("proto file does not have a UUID")
}
// ok, uuid is here
f.Uuid = line
log.Info("found UUID:", line)
scanner.Scan()
2025-01-09 15:03:05 -06:00
line = scanner.Text()
fields = strings.Fields(line)
// log.Info("GOT LINE", line)
2025-01-09 15:03:05 -06:00
if fields[0] == "string" && fields[1] != "version" {
2025-01-12 06:13:42 -06:00
f.noUuid()
2025-01-09 15:03:05 -06:00
return fmt.Errorf("proto file does not have a version")
}
// found "version", the .proto file conforms
f.Version = line
log.Info("found Version:", line)
return nil
}
2025-01-12 06:13:42 -06:00
f.noPluralMessage()
2025-01-09 15:03:05 -06:00
return fmt.Errorf("proto file error %s", f.Filename)
}
func (pb *Files) protoParse(pf *File) error {
2025-01-09 15:03:05 -06:00
// does the file conform to the standard? (also reads in UUID & Version)
if err := pb.hasPluralMessage(pf); err != nil {
2025-01-09 15:03:05 -06:00
return err
}
log.Info(pf.Filename, "is valid so far")
2025-01-09 15:03:05 -06:00
// read in the .proto file
data, err := os.ReadFile(pf.Filename)
if err != nil {
return err
}
2025-01-08 20:58:29 -06:00
var curmsg *MsgName
// parse the proto file for message struct names
2025-01-08 20:52:47 -06:00
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "message ") {
curmsg = pf.parseForMessage(line)
2025-01-08 20:58:29 -06:00
}
// this logic isn't right. find end of message with more bravado
2025-01-08 20:58:29 -06:00
if strings.HasPrefix(line, "}") {
curmsg = nil
2025-01-08 20:52:47 -06:00
}
2025-01-09 15:03:05 -06:00
if curmsg == nil {
// log.Info("curmsg == nil", line)
2025-01-09 15:03:05 -06:00
// can't contiue on nil below here
continue
}
// log.Info("curmsg != nil", line)
2025-01-08 20:52:47 -06:00
parts := strings.Fields(line)
2025-01-10 11:22:08 -06:00
msgvar := parseMsgVar(line)
if msgvar == nil {
// log.Info("Junk in .proto file? line did not contain a message var:", line)
continue
}
if msgvar.IsRepeated {
log.Info("ADDING ITER MAP", curmsg.Name, msgvar.VarType)
pf.IterMap[curmsg.Name] = msgvar.VarType
}
2025-01-09 03:42:29 -06:00
if strings.Contains(line, "autogenpb:sort") {
newS := cases.Title(language.English, cases.NoLower).String(parts[1])
2025-01-09 15:03:05 -06:00
log.Info("Addded Sort:", newS, "in struct", curmsg.Name)
curmsg.Sort = append(curmsg.Sort, newS)
2025-01-10 11:22:08 -06:00
msgvar.HasSort = true
}
2025-01-09 04:22:11 -06:00
if strings.Contains(line, "autogenpb:unique") {
2025-01-09 15:03:05 -06:00
newU := parts[1]
newU = cases.Title(language.English, cases.NoLower).String(newU)
log.Info("Added Unique:", newU, "in struct", curmsg.Name)
curmsg.Unique = append(curmsg.Unique, newU)
2025-01-10 11:22:08 -06:00
msgvar.HasUnique = true
}
2025-01-10 11:22:08 -06:00
curmsg.Vars = append(curmsg.Vars, msgvar)
}
pf.makeSortTable()
// for i, s := range slices.Backward(pf.ToSort) {
return nil
}
2024-12-01 22:21:09 -06:00
func (pf *File) makeSortTable() {
pf.sortWhat(pf.Bases)
pf.sortWhat(pf.Base)
// everything else
for _, msg := range pf.MsgNames {
pf.sortWhat(msg)
}
}
func (pf *File) sortWhat(msg *MsgName) {
for _, v := range msg.Vars {
if !v.IsRepeated {
continue
}
if check := pf.findMsg(v.VarType); check == nil {
// the VarType must be a struct
continue
}
s := new(Sort)
s.MsgName = msg.Name
s.VarType = v.VarType
s.VarName = v.VarName
s.Lockname = msg.Lockname
pf.ToSort = append(pf.ToSort, s)
}
}
2025-01-10 11:22:08 -06:00
func parseMsgVar(line string) *MsgVar {
if strings.Contains(line, "//") {
parts := strings.Split(line, "//")
if len(parts) == 0 {
// log.Info("parseMsgVar() nothing line", line)
return nil
}
line = parts[0]
}
parts := strings.Fields(line)
if len(parts) < 3 {
// log.Info("parseMsgVar() len < 3", parts)
return nil
}
if parts[0] == "message" {
// this is the struct
return nil
}
v := new(MsgVar)
if parts[0] == "repeated" {
v.IsRepeated = true
v.VarType = parts[1]
2025-01-11 10:19:37 -06:00
v.VarName = cases.Title(language.English, cases.NoLower).String(parts[2])
2025-01-10 11:22:08 -06:00
return v
}
v.VarType = parts[0]
2025-01-11 10:19:37 -06:00
v.VarName = cases.Title(language.English, cases.NoLower).String(parts[1])
2025-01-10 11:22:08 -06:00
return v
}
2025-01-08 20:52:47 -06:00
// looks for mutex and marshal entries
func (pf *File) parseForMessage(line string) *MsgName {
2025-01-08 20:52:47 -06:00
fields := strings.Fields(line)
if len(fields) == 0 || fields[0] != "message" {
2025-01-08 20:58:29 -06:00
return nil
2025-01-08 20:52:47 -06:00
}
var msg *MsgName
msg = new(MsgName)
base := cases.Title(language.English, cases.NoLower).String(pf.Filebase)
prefix := "message " + base + "s {" // only look for this for now
if strings.HasPrefix(line, prefix) {
pf.Bases = msg
} else {
prefix := "message " + base + " {" // only look for this for now
if strings.HasPrefix(line, prefix) {
pf.Base = msg
} else {
pf.MsgNames = append(pf.MsgNames, msg)
}
}
2025-01-09 15:29:27 -06:00
msgName := cases.Title(language.English, cases.NoLower).String(fields[1])
2025-01-09 15:03:05 -06:00
log.Info("found messge:", msgName)
2025-01-08 20:52:47 -06:00
msg.Name = msgName
msg.Lockname = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex
msg.NeedIter = true
2025-01-08 20:52:47 -06:00
if strings.Contains(line, "`autogenpb:mutex`") {
msg.DoMutex = true
2025-01-09 04:03:30 -06:00
log.Info("Added Mutex=true:", msg.Name)
2025-01-08 20:52:47 -06:00
}
if strings.Contains(line, "`autogenpb:nomutex`") {
msg.NoMutex = true
log.Info("Added Mutex=true:", msg.Name)
}
2025-01-08 20:52:47 -06:00
if strings.Contains(line, "`autogenpb:marshal`") {
msg.DoMarshal = true
2025-01-09 04:03:30 -06:00
log.Info("Added Marshal=true:", msg.Name)
2025-01-08 20:52:47 -06:00
}
2025-01-08 20:58:29 -06:00
return msg
2025-01-08 20:52:47 -06:00
}