compiles again
This commit is contained in:
parent
e725c0cc80
commit
ff1721c250
4
Makefile
4
Makefile
|
@ -25,7 +25,7 @@ install:
|
||||||
|
|
||||||
auto:
|
auto:
|
||||||
rm -f auto.pb.go
|
rm -f auto.pb.go
|
||||||
./autogenpb --proto auto.proto --package main
|
./autogenpb --proto file.proto --package main
|
||||||
rm -f auto.sort.pb.go auto.newsort.pb.go # auto.marshal.pb.go
|
rm -f auto.sort.pb.go auto.newsort.pb.go # auto.marshal.pb.go
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
@ -33,7 +33,7 @@ test:
|
||||||
|
|
||||||
junk:
|
junk:
|
||||||
cd example; rm -f go.* *.pb.go
|
cd example; rm -f go.* *.pb.go
|
||||||
cd example; ../autogenpb --proto auto.proto --package yellow
|
cd example; ../autogenpb --proto file.proto --package yellow
|
||||||
cd example; GO111MODULE=off go vet
|
cd example; GO111MODULE=off go vet
|
||||||
|
|
||||||
goimports:
|
goimports:
|
||||||
|
|
61
auto.proto
61
auto.proto
|
@ -1,5 +1,9 @@
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
// Look at "example/fruit.proto" not this file
|
||||||
|
|
||||||
|
// this file is actually used by autogenpb
|
||||||
|
|
||||||
// here are some docs, but probably it's just easier to run
|
// here are some docs, but probably it's just easier to run
|
||||||
// autogenpb on this file and see what gets autogenerated
|
// autogenpb on this file and see what gets autogenerated
|
||||||
// in this directory. All autogenerated files are named *.pb.go
|
// in this directory. All autogenerated files are named *.pb.go
|
||||||
|
@ -15,26 +19,6 @@ syntax = "proto3";
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
message Apple { // `autogenpb:marshal`
|
|
||||||
string name = 1; // `autogenpb:unique` // generates SortByxxx() and AppendUnique() functions
|
|
||||||
string genus = 2; // `autogenpb:unique` // generates same thing here but SortByGenus()
|
|
||||||
}
|
|
||||||
|
|
||||||
message Apples { // `autogenpb:marshal` `autogenpb:mutex`
|
|
||||||
string uuid = 1; // `autogenpb:default:b2a2de35-07b6-443b-8188-709e27bee8a7`
|
|
||||||
string version = 2; // `autogenpb:default:2`
|
|
||||||
repeated Apple Apples = 3; // `autogenpb:sort`
|
|
||||||
repeated Pears More = 4; // `autogenpb:sort`
|
|
||||||
repeated string Color = 5; // `autogenpb:sort` `autogenpb:unique`
|
|
||||||
}
|
|
||||||
|
|
||||||
message Pears {
|
|
||||||
string name = 1; //
|
|
||||||
string favorite = 2; // `autogenpb:sort`
|
|
||||||
}
|
|
||||||
|
|
||||||
// above is an example
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// below are the actual structs autogen uses
|
// below are the actual structs autogen uses
|
||||||
// autogen parses the .proto file and then store the information
|
// autogen parses the .proto file and then store the information
|
||||||
|
@ -42,34 +26,13 @@ message Pears {
|
||||||
// protobuf files to write out *.sort.pb.go and *.marshal.pb.go files
|
// protobuf files to write out *.sort.pb.go and *.marshal.pb.go files
|
||||||
//
|
//
|
||||||
message MsgName {
|
message MsgName {
|
||||||
// If you have:
|
|
||||||
//
|
|
||||||
// "Shelf" for msgname
|
|
||||||
// "Books" for name
|
|
||||||
//
|
|
||||||
// Then in the proto file, that would mean it would look like:
|
|
||||||
//
|
|
||||||
// message Shelf {
|
|
||||||
// and then
|
|
||||||
// repeated string Books = 42;
|
|
||||||
//
|
|
||||||
// autogenpb will then generate sort functions for each 'name'
|
|
||||||
// things like:
|
|
||||||
//
|
|
||||||
// for _, b := range all.Book {
|
|
||||||
//
|
|
||||||
// and sort functions like:
|
|
||||||
//
|
|
||||||
// func (a ShelfBook) Less(i, j int) bool { return a[i].Book < a[j].Book }
|
|
||||||
//
|
|
||||||
|
|
||||||
string name = 1; // the name of the message aka struct. for this example: "Shelf"
|
string name = 1; // the name of the message aka struct. for this example: "Shelf"
|
||||||
string lockname = 2; // ShelfMU
|
string lockname = 2; // name of the lockfile. ends in Mu
|
||||||
bool doMarshal = 3; // if "Shelf" should have Marshal & Unmarshal functions
|
bool doMarshal = 3; // if msg struct should have Marshal & Unmarshal functions
|
||||||
bool doMutex = 4; // true if a mutex is needed for the message struct
|
bool doMutex = 4; // true if a mutex is needed for the message struct
|
||||||
bool doProtocMutex = 5; // an experiment to insert a mutex into the protoc generated msg struct (bad idea?)
|
bool doProtocMutex = 5; // an experiment to insert a mutex into the protoc generated msg struct (bad idea?)
|
||||||
bool mutexFound = 6; // true if the mutex was added to the protoc pb.go file
|
bool mutexFound = 6; // true if the mutex was added to the protoc pb.go file
|
||||||
repeated string sort = 7; // "Book", "Picture", etc
|
repeated string sort = 7; // keys to sort on
|
||||||
repeated string unique = 8; // if the fields should have AppendUnique() functions
|
repeated string unique = 8; // if the fields should have AppendUnique() functions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,10 +42,12 @@ message File { // `autogenpb:nomarshal`
|
||||||
string pbfilename = 3; // yellow.pb.go
|
string pbfilename = 3; // yellow.pb.go
|
||||||
string filebase = 4; // yellow
|
string filebase = 4; // yellow
|
||||||
string uuid = 5; // the uuid to use in a func NewMsgName()
|
string uuid = 5; // the uuid to use in a func NewMsgName()
|
||||||
int64 version = 6; // the version to use in a func NewMsgName()
|
string version = 6; // the version to use in a func NewMsgName()
|
||||||
|
MsgName bases = 7; // the message in "plural" form
|
||||||
|
MsgName base = 8; // the primary repeated message for the master struct
|
||||||
|
|
||||||
// every struct in this proto file, this file has: "Apple", "Apples", ... "File", etc...
|
// every struct in this proto file, this file has: "Apple", "Apples", ... "File", etc...
|
||||||
repeated MsgName msgNames = 7; // `autogenpb:unique` // in this file
|
repeated MsgName msgNames = 9; // `autogenpb:unique` // in this file
|
||||||
}
|
}
|
||||||
|
|
||||||
// I know, I know, the whole point of using protobuf
|
// I know, I know, the whole point of using protobuf
|
||||||
|
@ -92,8 +57,8 @@ message File { // `autogenpb:nomarshal`
|
||||||
// also, this could be used to modify /usr/bin/file /usr/share/magic to identify the files
|
// also, this could be used to modify /usr/bin/file /usr/share/magic to identify the files
|
||||||
// maybe this is already been done and is pointless, but it seems like a good idea
|
// maybe this is already been done and is pointless, but it seems like a good idea
|
||||||
message Files { // `autogenpb:marshal`
|
message Files { // `autogenpb:marshal`
|
||||||
string uuid = 1; // if you use this scheme, autogen will be able to identify your
|
string uuid = 1; // `autogenpb:uuid:6c9ae4dd-648d-4b51-9738-bd59fb8fafd5`
|
||||||
int64 version = 2; // protobuf files from the command line.
|
string version = 2; // `autogenpb:version:v0.0.38`
|
||||||
repeated File Files = 3; // an array of each .proto file in the working directory
|
repeated File Files = 3; // an array of each .proto file in the working directory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,6 @@ package main
|
||||||
func NewFruits() *Fruits {
|
func NewFruits() *Fruits {
|
||||||
x := new(Fruits)
|
x := new(Fruits)
|
||||||
x.Uuid = "test"
|
x.Uuid = "test"
|
||||||
|
x.Version = "v0.0.2"
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
// Look at "example/fruit.proto" not this file
|
||||||
|
|
||||||
|
// this file is actually used by autogenpb
|
||||||
|
|
||||||
|
// here are some docs, but probably it's just easier to run
|
||||||
|
// autogenpb on this file and see what gets autogenerated
|
||||||
|
// in this directory. All autogenerated files are named *.pb.go
|
||||||
|
|
||||||
|
// the 'uuid' standard at the end is an experiment
|
||||||
|
// establish a way to identify arbitrary .pb files
|
||||||
|
|
||||||
|
// You can generate Marshal & Unmarshal for any struct (message) you want
|
||||||
|
// You can generate SortBy and Append functions ONLY FOR 'repeated <message>'
|
||||||
|
// Also, those structs must be defined in the same file
|
||||||
|
// Additionally, you must use `autogenpb:mutex` on the parent struct.
|
||||||
|
// The autogenerated code requires a RW mutex and autogenpb will insert it into the struct
|
||||||
|
|
||||||
|
package main;
|
||||||
|
|
||||||
|
//
|
||||||
|
// below are the actual structs autogen uses
|
||||||
|
// autogen parses the .proto file and then store the information
|
||||||
|
// it needs in these protobuf files, then it processes the
|
||||||
|
// protobuf files to write out *.sort.pb.go and *.marshal.pb.go files
|
||||||
|
//
|
||||||
|
message MsgName {
|
||||||
|
string name = 1; // the name of the message aka struct. for this example: "Shelf"
|
||||||
|
string lockname = 2; // name of the lockfile. ends in Mu
|
||||||
|
bool doMarshal = 3; // if msg struct should have Marshal & Unmarshal functions
|
||||||
|
bool doMutex = 4; // true if a mutex is needed for the message struct
|
||||||
|
bool doProtocMutex = 5; // an experiment to insert a mutex into the protoc generated msg struct (bad idea?)
|
||||||
|
bool mutexFound = 6; // true if the mutex was added to the protoc pb.go file
|
||||||
|
repeated string sort = 7; // keys to sort on
|
||||||
|
repeated string unique = 8; // if the fields should have AppendUnique() functions
|
||||||
|
}
|
||||||
|
|
||||||
|
message File { // `autogenpb:nomarshal`
|
||||||
|
string Package = 1; // whatever the package name is at the top of the .go file
|
||||||
|
string filename = 2; // yellow.proto
|
||||||
|
string pbfilename = 3; // yellow.pb.go
|
||||||
|
string filebase = 4; // yellow
|
||||||
|
string uuid = 5; // the uuid to use in a func NewMsgName()
|
||||||
|
string version = 6; // the version to use in a func NewMsgName()
|
||||||
|
MsgName bases = 7; // the message in "plural" form
|
||||||
|
MsgName base = 8; // the primary repeated message for the master struct
|
||||||
|
|
||||||
|
// every struct in this proto file, this file has: "Apple", "Apples", ... "File", etc...
|
||||||
|
repeated MsgName msgNames = 9; // `autogenpb:unique` // in this file
|
||||||
|
}
|
||||||
|
|
||||||
|
// I know, I know, the whole point of using protobuf
|
||||||
|
// is so you don't need a uuid or versions because it's
|
||||||
|
// inherently forward compatable. nonetheless, a simple stubbed out
|
||||||
|
// trivial and empty protobuf message can marshal and identify all the files
|
||||||
|
// also, this could be used to modify /usr/bin/file /usr/share/magic to identify the files
|
||||||
|
// maybe this is already been done and is pointless, but it seems like a good idea
|
||||||
|
message Files { // `autogenpb:marshal`
|
||||||
|
string uuid = 1; // `autogenpb:uuid:6c9ae4dd-648d-4b51-9738-bd59fb8fafd5`
|
||||||
|
string version = 2; // `autogenpb:version:v0.0.38`
|
||||||
|
repeated File Files = 3; // an array of each .proto file in the working directory
|
||||||
|
}
|
||||||
|
|
||||||
|
// this generic message is used by autogen to identify and
|
||||||
|
// then dump the uuid and version from any arbitrary .pb file
|
||||||
|
message Identify { // `autogenpb:marshal`
|
||||||
|
string uuid = 1; //
|
||||||
|
int64 version = 2; //
|
||||||
|
}
|
8
main.go
8
main.go
|
@ -108,16 +108,10 @@ func main() {
|
||||||
protobase := strings.TrimSuffix(argv.Proto, ".proto")
|
protobase := strings.TrimSuffix(argv.Proto, ".proto")
|
||||||
f.Filebase = protobase
|
f.Filebase = protobase
|
||||||
|
|
||||||
// parse the .proto file
|
|
||||||
if err := pb.protoParse(f); err != nil {
|
|
||||||
log.Info("autogenpb parse error:", err)
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse sort & marshal options from the .proto file
|
// parse sort & marshal options from the .proto file
|
||||||
// this goes through the .proto files and looks
|
// this goes through the .proto files and looks
|
||||||
// for `autogenpb: ` lines
|
// for `autogenpb: ` lines
|
||||||
if err := pb.protoParseNew(f); err != nil {
|
if err := pb.protoParse(f); err != nil {
|
||||||
log.Info("autogenpb parse error:", err)
|
log.Info("autogenpb parse error:", err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func marshalThing(w io.Writer, thing string) {
|
||||||
fmt.Fprintln(w, "")
|
fmt.Fprintln(w, "")
|
||||||
fmt.Fprintln(w, "// apparently this isn't stable, but it's awesomely better")
|
fmt.Fprintln(w, "// apparently this isn't stable, but it's awesomely better")
|
||||||
fmt.Fprintln(w, "// https://protobuf.dev/reference/go/faq/#unstable-text")
|
fmt.Fprintln(w, "// https://protobuf.dev/reference/go/faq/#unstable-text")
|
||||||
fmt.Fprintln(w, "// it's so great for config files, I'm using it by default to try to fix the problems with it")
|
fmt.Fprintln(w, "// it's brilliant for config files!")
|
||||||
fmt.Fprintln(w, "func (v *"+thing+") FormatTEXT() string {")
|
fmt.Fprintln(w, "func (v *"+thing+") FormatTEXT() string {")
|
||||||
fmt.Fprintln(w, " return prototext.Format(v)")
|
fmt.Fprintln(w, " return prototext.Format(v)")
|
||||||
fmt.Fprintln(w, "}")
|
fmt.Fprintln(w, "}")
|
||||||
|
|
131
protoParse.go
131
protoParse.go
|
@ -3,6 +3,8 @@ package main
|
||||||
// auto run protoc with the correct args
|
// auto run protoc with the correct args
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -13,15 +15,59 @@ import (
|
||||||
|
|
||||||
// this parses the .proto file and handles anything with `autogenpb: `
|
// this parses the .proto file and handles anything with `autogenpb: `
|
||||||
|
|
||||||
// finds autogenpb:marshal and autogenpb:unique in the .proto file
|
// does the fruit.proto file have "message Fruits"
|
||||||
//
|
func (pb *Files) hasPluralMessage(f *File) error {
|
||||||
// adds fields to []marshal and []unique
|
file, err := os.Open(f.Filename)
|
||||||
func (pb *Files) protoParseNew(f *File) error {
|
if err != nil {
|
||||||
// log.Info("starting findAutogenpb() on", names["protofile"])
|
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
|
||||||
|
}
|
||||||
|
// found the matching message
|
||||||
|
// f.Bases = f.parseForMessage(line)
|
||||||
|
|
||||||
|
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(f *File) error {
|
||||||
|
// does the file conform to the standard? (also reads in UUID & Version)
|
||||||
|
if err := pb.hasPluralMessage(f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info(f.Filename, "is valid so far")
|
||||||
|
|
||||||
// read in the .proto file
|
// read in the .proto file
|
||||||
data, err := os.ReadFile(f.Filename)
|
data, err := os.ReadFile(f.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// log.Info("open config file :", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,45 +75,38 @@ func (pb *Files) protoParseNew(f *File) error {
|
||||||
|
|
||||||
// parse the proto file for message struct names
|
// parse the proto file for message struct names
|
||||||
for _, line := range strings.Split(string(data), "\n") {
|
for _, line := range strings.Split(string(data), "\n") {
|
||||||
|
base := cases.Title(language.English, cases.NoLower).String(f.Filebase)
|
||||||
if strings.HasPrefix(line, "message ") {
|
if strings.HasPrefix(line, "message ") {
|
||||||
curmsg = f.parseForMessage(line)
|
curmsg = f.parseForMessage(line)
|
||||||
|
prefix := "message " + base // only look for this for now
|
||||||
|
if strings.HasPrefix(line, prefix) {
|
||||||
|
// f.Base = curmsg
|
||||||
|
} else {
|
||||||
|
f.MsgNames = append(f.MsgNames, curmsg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "}") {
|
if strings.HasPrefix(line, "}") {
|
||||||
curmsg = nil
|
curmsg = nil
|
||||||
}
|
}
|
||||||
|
if curmsg == nil {
|
||||||
|
// can't contiue on nil below here
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// log.Info("line:", line)
|
// log.Info("line:", line)
|
||||||
parts := strings.Fields(line)
|
parts := strings.Fields(line)
|
||||||
|
|
||||||
if strings.Contains(line, "autogenpb:sort") {
|
if strings.Contains(line, "autogenpb:sort") {
|
||||||
if parts[0] == "repeated" {
|
newS := parts[1]
|
||||||
newS := parts[1]
|
log.Info("Addded Sort:", newS, "in struct", curmsg.Name)
|
||||||
if curmsg == nil {
|
curmsg.Sort = append(curmsg.Sort, newS)
|
||||||
log.Info("Error: Found Sort for:", newS, "however, this struct can't be used")
|
|
||||||
} else {
|
|
||||||
log.Info("Addded Sort:", newS, "in struct", curmsg.Name)
|
|
||||||
curmsg.Sort = append(curmsg.Sort, newS)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Info("Error:", line)
|
|
||||||
log.Info("Error: can not sort on non repeated fields")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(line, "autogenpb:unique") {
|
if strings.Contains(line, "autogenpb:unique") {
|
||||||
if parts[0] == "repeated" {
|
newU := parts[1]
|
||||||
newU := parts[1]
|
newU = cases.Title(language.English, cases.NoLower).String(newU)
|
||||||
newU = cases.Title(language.English, cases.NoLower).String(newU)
|
log.Info("Added Unique:", newU, "in struct", curmsg.Name)
|
||||||
if curmsg == nil {
|
curmsg.Unique = append(curmsg.Unique, newU)
|
||||||
log.Info("Error: Found Unique for:", newU, "however, this struct can't be used")
|
|
||||||
} else {
|
|
||||||
log.Info("Added Unique:", newU, "in struct", curmsg.Name)
|
|
||||||
curmsg.Unique = append(curmsg.Unique, newU)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Info("Error:", line)
|
|
||||||
log.Info("Error: can not append on non repeated fields")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -80,8 +119,8 @@ func (f *File) parseForMessage(line string) *MsgName {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
msgName := fields[1]
|
msgName := fields[1]
|
||||||
|
log.Info("found messge:", msgName)
|
||||||
msg := new(MsgName)
|
msg := new(MsgName)
|
||||||
f.MsgNames = append(f.MsgNames, msg)
|
|
||||||
msg.Name = msgName
|
msg.Name = msgName
|
||||||
msg.Lockname = msgName + "Mu"
|
msg.Lockname = msgName + "Mu"
|
||||||
|
|
||||||
|
@ -95,31 +134,3 @@ func (f *File) parseForMessage(line string) *MsgName {
|
||||||
}
|
}
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// this doesn't do anything anymore (?)
|
|
||||||
func (pb *Files) protoParse(f *File) error {
|
|
||||||
// log.Info("starting findAutogenpb() on", filename)
|
|
||||||
// read in the .proto file
|
|
||||||
data, err := os.ReadFile(f.Filename)
|
|
||||||
if err != nil {
|
|
||||||
// log.Info("open config file :", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(data), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.Contains(line, "autogenpb:ignoreproto") {
|
|
||||||
// ignore this protofile completely (don't make foo.pb.go)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
if strings.Contains(line, "autogenpb:no-marshal") {
|
|
||||||
// don't marshal anything (don't make foo.marshal.pb.go)
|
|
||||||
argv.NoMarshal = true
|
|
||||||
}
|
|
||||||
if strings.Contains(line, "autogenpb:no-sort") {
|
|
||||||
// don't sort anything (don't make foo.sort.pb.go)
|
|
||||||
argv.NoSort = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue