219 lines
5.4 KiB
Go
219 lines
5.4 KiB
Go
package main
|
|
|
|
// auto run protoc with the correct args
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"go.wit.com/log"
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
// this parses the .proto file and handles anything with `autogenpb: `
|
|
|
|
// 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)
|
|
prefix := "message " + base + "s {" // to conform, it must have an added 's'
|
|
if !strings.HasPrefix(line, prefix) {
|
|
// log.Info("nope", prefix, "line", line)
|
|
// nope, not this line
|
|
continue
|
|
}
|
|
|
|
line = scanner.Text()
|
|
fields := strings.Fields(line)
|
|
if fields[0] == "string" && fields[1] != "uuid" {
|
|
return fmt.Errorf("proto file does not have a UUID")
|
|
}
|
|
// ok, uuid is here
|
|
f.Uuid = line
|
|
log.Info("found UUID:", line)
|
|
|
|
line = scanner.Text()
|
|
fields = strings.Fields(line)
|
|
if fields[0] == "string" && fields[1] != "version" {
|
|
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
|
|
}
|
|
return fmt.Errorf("proto file error %s", f.Filename)
|
|
}
|
|
|
|
func (pb *Files) protoParse(pf *File) error {
|
|
// does the file conform to the standard? (also reads in UUID & Version)
|
|
if err := pb.hasPluralMessage(pf); err != nil {
|
|
return err
|
|
}
|
|
log.Info(pf.Filename, "is valid so far")
|
|
|
|
// read in the .proto file
|
|
data, err := os.ReadFile(pf.Filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var curmsg *MsgName
|
|
|
|
// parse the proto file for message struct names
|
|
for _, line := range strings.Split(string(data), "\n") {
|
|
if strings.HasPrefix(line, "message ") {
|
|
curmsg = pf.parseForMessage(line)
|
|
}
|
|
// this logic isn't right. find end of message with more bravado
|
|
if strings.HasPrefix(line, "}") {
|
|
curmsg = nil
|
|
}
|
|
if curmsg == nil {
|
|
// log.Info("curmsg == nil", line)
|
|
// can't contiue on nil below here
|
|
continue
|
|
}
|
|
// log.Info("curmsg != nil", line)
|
|
|
|
parts := strings.Fields(line)
|
|
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
|
|
}
|
|
|
|
if strings.Contains(line, "autogenpb:sort") {
|
|
newS := cases.Title(language.English, cases.NoLower).String(parts[1])
|
|
log.Info("Addded Sort:", newS, "in struct", curmsg.Name)
|
|
curmsg.Sort = append(curmsg.Sort, newS)
|
|
msgvar.HasSort = true
|
|
}
|
|
|
|
if strings.Contains(line, "autogenpb:unique") {
|
|
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)
|
|
msgvar.HasUnique = true
|
|
}
|
|
curmsg.Vars = append(curmsg.Vars, msgvar)
|
|
}
|
|
pf.makeSortTable()
|
|
|
|
// for i, s := range slices.Backward(pf.ToSort) {
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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]
|
|
v.VarName = cases.Title(language.English, cases.NoLower).String(parts[2])
|
|
return v
|
|
}
|
|
v.VarType = parts[0]
|
|
v.VarName = cases.Title(language.English, cases.NoLower).String(parts[1])
|
|
return v
|
|
}
|
|
|
|
// looks for mutex and marshal entries
|
|
func (pf *File) parseForMessage(line string) *MsgName {
|
|
fields := strings.Fields(line)
|
|
if len(fields) == 0 || fields[0] != "message" {
|
|
return nil
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
|
|
msgName := cases.Title(language.English, cases.NoLower).String(fields[1])
|
|
log.Info("found messge:", msgName)
|
|
msg.Name = msgName
|
|
msg.Lockname = pf.Filebase + "Mu" // this should be lowercase. do not export the Mutex
|
|
msg.NeedIter = true
|
|
|
|
if strings.Contains(line, "`autogenpb:mutex`") {
|
|
msg.DoMutex = true
|
|
log.Info("Added Mutex=true:", msg.Name)
|
|
}
|
|
if strings.Contains(line, "`autogenpb:marshal`") {
|
|
msg.DoMarshal = true
|
|
log.Info("Added Marshal=true:", msg.Name)
|
|
}
|
|
return msg
|
|
}
|