summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile28
-rw-r--r--example/Makefile18
-rw-r--r--example/file.proto1
-rw-r--r--example/fruit.proto33
-rw-r--r--file.proto20
-rw-r--r--generate.go276
-rw-r--r--generateSort.go80
-rw-r--r--human.go88
-rw-r--r--main.go23
-rw-r--r--protoParse.go46
10 files changed, 541 insertions, 72 deletions
diff --git a/Makefile b/Makefile
index 7f0b91d..049a547 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,27 @@
VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
-simple: build
- make -C example clean simpleMutexGlobal goimports vet
- make -C example clean simpleMutexProtoc goimports vet
+simple: test
+ # make -C example clean simpleMutexGlobal goimports vet
+ # make -C example clean simpleMutexProtoc goimports vet
# make -C example deleteproto
full: install clean auto goimports vet build test install
@echo everything worked and the example ran
-test: goimports build test
+
+# if this passes, it should be OK to 'go install'
+test:
+ reset
+ make goimports vet build
+ make -C example testGlobal
+ make -C example testProtoc
+
+dryrun: build
+ make -C example dryrun
+
+dryrun-clean: clean auto build
+ make -C example dryrun
vet:
@GO111MODULE=off go vet
@@ -31,7 +43,7 @@ build: goimports
bak:
mv -f autogenpb autogenpb.last
-install:
+install: test
GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
@@ -40,12 +52,6 @@ auto:
autogenpb --proto file.proto --package main
# rm -f auto.sort.pb.go auto.newsort.pb.go # auto.marshal.pb.go
-test:
- make -C example rawproto
- # The Go Protocol Buffers library embeds a sync.Mutex within the MessageState struct to prevent unintended shallow copies of message structs
- # It only fails in Marshal() functions though. That is dumb.
- make -C example modproto # THIS DOES NOT WORK. It could work however. This autogenerated code could be used to debug it.
-
junk:
cd example; rm -f go.* *.pb.go
cd example; ../autogenpb --proto file.proto --package yellow
diff --git a/example/Makefile b/example/Makefile
index 22a8c65..3a045bd 100644
--- a/example/Makefile
+++ b/example/Makefile
@@ -4,6 +4,20 @@ BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
all: clean simpleMutexProtoc goimports build
./example
+# if this passes, then autogenpb should be working
+# and it is OK to 'go install' the binary
+test: testGlobal testProtoc
+
+testGlobal:
+ make clean
+ ../autogenpb --proto fruit.proto --package main --mutex=false # first build with a global mutex
+ make build
+
+testProtoc:
+ make clean
+ ../autogenpb --proto fruit.proto --package main # inserts mutex into protoc .pb.go file
+ make build
+
modproto: clean withMutex goimports vet build
./example
@@ -47,6 +61,10 @@ withoutMutex: clean
../autogenpb --proto file.proto --package main --mutex=false
../autogenpb --proto patchset.proto --package main --mutex=false
+dryrun:
+ ../autogenpb --proto fruit.proto --package main --dry-run
+ # ../autogenpb --proto file.proto --package main
+
goimports:
goimports -w *.go
diff --git a/example/file.proto b/example/file.proto
index 18b096a..2f1b377 100644
--- a/example/file.proto
+++ b/example/file.proto
@@ -41,6 +41,7 @@ message MsgName {
repeated string sort = 7; // keys to sort on
repeated string unique = 8; // if the fields should have AppendUnique() functions
repeated MsgVar vars = 9; // store all the vars in the message
+ bool needIter = 10; // true if the sort iterator has not been generated yet
}
message File {
diff --git a/example/fruit.proto b/example/fruit.proto
index 92e46ef..d43a741 100644
--- a/example/fruit.proto
+++ b/example/fruit.proto
@@ -22,17 +22,35 @@ message Apple { // `autogenpb:marshal`
}
message Pear {
- string name = 1; //
- string favorite = 2; // `autogenpb:sort`
+ string name = 1; // `autogenpb:sort`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+}
+
+message Banana {
+ repeated string name = 1; // `autogenpb:sort`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ string country = 3; // `autogenpb:sort`
+}
+
+message Basket {
+ repeated string name = 1; // `autogenpb:sort` `autogenpb:unique`
+ string favorite = 2; // `autogenpb:sort` `autogenpb:unique`
+ int64 price = 3; // `autogenpb:sort`
+ repeated Banana banna = 4;
+ repeated Pear pears = 5;
+ repeated Apple stacks = 6;
}
// "Fruit" must exist. you can put anything in it
message Fruit { // `autogenpb:marshal`
- string brand = 1; // `autogenpb:unique` `autogenpb:sort`
- repeated Apple apples = 2;
- repeated Pear pears = 3;
- string UPC = 4; // `autogenpb:sort` `autogenpb:unique`
- string city = 5; // `autogenpb:sort`
+ string brand = 1; // `autogenpb:unique` `autogenpb:sort`
+ repeated Apple apples = 2;
+ repeated Pear pears = 3;
+ string UPC = 4; // `autogenpb:sort` `autogenpb:unique`
+ string city = 5; // `autogenpb:sort`
+ repeated Pear notpears = 6;
+ repeated Pear fakepears = 7;
+ repeated Basket gifts = 8;
}
// "Fruits" MUST EXIST and start exactly this way
@@ -43,4 +61,5 @@ message Fruits { // `autogenpb:marshal` `autogenpb:mutex`
repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s"
// you can add additional things here but the three lines above must conform to the standard above
int64 cost = 4;
+ map<string, string> junk = 5;
}
diff --git a/file.proto b/file.proto
index bb9f614..f2f6887 100644
--- a/file.proto
+++ b/file.proto
@@ -43,9 +43,27 @@ message MsgName {
repeated string sort = 7; // keys to sort on
repeated string unique = 8; // if the fields should have AppendUnique() functions
repeated MsgVar vars = 9; // store all the vars in the message
+ bool needIter = 10; // true if the sort iterator has not been generated yet
+ bool needAll = 11; // true if the sort iterator has not been generated yet
+}
+
+message Sort {
+ string msgName = 1; // `autogenpb:unique` File
+ string varType = 2; // `autogenpb:unique` MsgName
+ string varName = 3; // `autogenpb:unique` msgNames, sortNames
+ string lockname = 4; //
+ bool needAll = 5; //
+}
+
+message Find {
+ string parent = 1; // `autogenpb:unique` File
+ string varType = 2; // `autogenpb:unique` MsgName
+ string varName = 3; // `autogenpb:unique` msgNames, sortNames
+ bool needAll = 4; //
}
message File {
+ // `autogenpb:var:w io.Writer`
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
@@ -58,6 +76,8 @@ message File {
// every struct in this proto file, this file has: "Apple", "Apples", ... "File", etc...
repeated MsgName msgNames = 9;
repeated MsgName sortNames = 10; // variables that are repeated can have the standard functions generated (Sort(), etc)
+ map<string, string> iterMap = 11;
+ repeated Sort toSort = 12; // variables that are repeated can have the standard functions generated (Sort(), etc)
}
// I know, I know, the whole point of using protobuf
diff --git a/generate.go b/generate.go
index b22b3f7..418513f 100644
--- a/generate.go
+++ b/generate.go
@@ -15,19 +15,212 @@ import (
func (pb *Files) makeNewSortfile(pf *File) error {
wSort, _ := os.OpenFile(pf.Filebase+".sort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
defer wSort.Close()
- wFind, _ := os.OpenFile(pf.Filebase+".find.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- defer wFind.Close()
header(wSort, pf)
+ pf.syncLock(wSort)
- // pf.Base.iterTop(wSort)
- // pf.Base.iterNext(wSort)
- // pf.selectAllFunc(wSort)
- // pf.iterSelect(wSort)
+ log.Printf("START ITERATORS\n")
+ // add iterators for all the structs to be used
+ for i, msg := range pf.allMsg() {
+ PARENT := msg.Name
+ LOCK := msg.Lockname
- // pf.sortByFunc(wSort, pf.Bases, pf.Base)
- pf.newGenerateSort(wSort, pf.Bases)
- pf.newGenerateSort(wSort, pf.Base)
+ funcdef := newIter(wSort, msg)
+ log.Printf("ITER: %-2d %20s %20s %20s %20s %s\n", i, PARENT, "", "", LOCK, funcdef)
+ }
+ log.Printf("END ITERATORS\n")
+ log.Printf("\n")
+
+ log.Printf("START COMPARE\n")
+ for i, msg := range pf.allMsg() {
+ PARENT := msg.Name
+ for _, v := range msg.Vars {
+ if !v.HasSort {
+ continue
+ }
+ VARNAME := v.VarName
+ funcdef := newSortType(wSort, PARENT, VARNAME)
+ log.Printf("TYPE: %-2d %20s %20s %20s %10s %s\n", i, PARENT, "", "", "", funcdef)
+ }
+ }
+ log.Printf("END COMPARE\n")
+ log.Printf("\n")
+
+ // add selectAll() functions for all the sort combinations that will be used
+ for i, s := range pf.ToSort {
+ // log.Printf("SORT: %-2d %20s %20s %20s %20s\n", i, s.MsgName, s.VarType, s.VarName, s.Lockname)
+ FRUIT := s.MsgName
+ APPLE := s.VarType
+ APPLES := s.VarName
+ LOCK := s.Lockname
+ funcdef := newIterAll(wSort, FRUIT, APPLE, APPLES, LOCK)
+ log.Printf("JUNK: %-2d %20s %20s %20s %20s %s\n", i, FRUIT, APPLE, "", LOCK, funcdef)
+ }
+ log.Printf("\n")
+
+ // make the sort iterators selectAll()
+ for i, s := range pf.ToSort {
+ PARENT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
+ LOCK := s.Lockname
+
+ funcdef := addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK)
+ log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, funcdef)
+ }
+ log.Printf("\n")
+
+ // make Len()
+ for _, msg := range pf.allMsg() {
+ PARENT := msg.Name
+ LOCK := msg.Lockname
+
+ for i, v := range msg.Vars {
+ if v.IsRepeated {
+ CHILD := v.VarType
+ VARNAME := v.VarName
+ // funcdef := "func (x *" + PARENT + ") Len" + VARNAME + "() int " + CHILD + " name:" + VARNAME
+
+ if PARENT == VARNAME {
+ // special case
+ funcdef := addLenFunc(wSort, PARENT, VARNAME, LOCK) // + " " + v.VarType + " name:" + v.VarName
+ funcdef += " # is special struct=varname"
+ log.Printf("LEN: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, funcdef)
+ }
+ }
+ }
+ }
+
+ log.Printf("\n")
+ log.Printf(" %-2s %20s %20s %20s %20s\n", "", "PARENT STRUCT", "VAR STRUCT TYPE", "VAR NAME", "LOCK")
+ // for i, s := range slices.Backward(pf.ToSort) {
+ for i, s := range pf.ToSort {
+ var funcname string
+ PARENT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
+ LOCK := s.Lockname
+
+ log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, PARENT, CHILD, VARNAME, LOCK, "")
+
+ var FUNCTYPE string
+ if PARENT == VARNAME {
+ FUNCTYPE = PARENT
+ } else {
+ FUNCTYPE = VARNAME
+ }
+
+ if PARENT == VARNAME {
+ funcname := addAllFunc(wSort, PARENT, CHILD, VARNAME)
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "done", "", funcname)
+ }
+ if s.VarType+"s" == s.VarName {
+ funcname = "func (x *" + FUNCTYPE + ") All() *[]iter" + s.VarType
+ } else {
+ funcname = "func (x *" + FUNCTYPE + ") all" + s.VarName + "() *[]iter" + s.VarType
+ }
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ msg := pf.findMsg(s.VarType)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
+ for _, v := range msg.Vars {
+ if v.HasSort {
+ funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ // funcdef := "func (x *"+FRUIT+") SortBy"+COLOR+"() *"+APPLE+"Iterator"
+
+ if v.VarType == "string" {
+ funcdef := newSortBy(wSort, FUNCTYPE, CHILD, VARNAME, v.VarName)
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcdef)
+ } else {
+ funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ }
+
+ var ucount int
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ ucount += 1
+ funcname := "func (x *" + FUNCTYPE + ") AppendUnique" + v.VarName + "(" + v.VarType + ")"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ funcname := "func (x *" + FUNCTYPE + ") DeleteBy" + v.VarName + "(" + v.VarType + ") bool"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ funcname = "func (x *" + FUNCTYPE + ") FindBy" + v.VarName + "(a " + v.VarType + ") *" + s.VarType + "(using" + v.VarName + ")"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ } else {
+ if v.VarType == "string" {
+ funcname = "func (x *" + FUNCTYPE + ") FindBy" + v.VarName + "(a string) []*" + s.VarType + " ???"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ }
+ if ucount == 1 {
+ for _, v := range msg.Vars {
+ if !v.HasUnique {
+ continue
+ }
+ funcname = "func (x *" + FUNCTYPE + ") Insert(a *" + v.VarType + ") (*" + CHILD + ", isNew bool)"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ if ucount > 1 {
+ funcname = "func (x *" + FUNCTYPE + ") Insert(a *" + CHILD + ") (*" + CHILD + ", isNew bool)"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+
+ }
+
+ /*
+ // everything struct used in here needs a sort iterator (but just one)
+ for FRUIT, APPLE := range pf.IterMap {
+ msg := pf.findMsg(FRUIT)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", FRUIT)
+ }
+ log.Printf("Add newIter() message %s\n", FRUIT)
+ newIter(wSort, msg)
+
+ child := pf.findMsg(APPLE)
+ if child == nil {
+ return fmt.Errorf("failed to find struct %s", APPLE)
+ }
+ log.Printf("Add newIter() message %s\n", APPLE)
+ newIter(wSort, child)
+
+ // now add the allKEY() functions
+ msg.newIterAll(wSort, FRUIT, APPLE)
+ }
+ */
+
+ /*
+ log.Info("START")
+ log.Printf("Add all() FRUIT=%s APPLE=%s\n", FRUIT, APPLE)
+ addAllFunc(w, FRUIT, APPLE, LOCK)
+ log.Printf("Add len() FRUIT=%s APPLES=%s\n", FRUIT, APPLES)
+ addLenFunc(w, FRUIT, APPLES, LOCK)
+ log.Printf("Add selectAll() FRUIT=%s APPLE=%s APPLES=%s\n", FRUIT, APPLE, APPLES)
+ addSelectAll(w, FRUIT, APPLE, APPLES, LOCK)
+ // newIter(w, FRUIT, APPLE, APPLES, LOCK)
+ log.Info("END")
+ */
+
+ /*
+ return nil
+ pf.newGenerateSort(wSort, pf.Bases)
+ pf.newGenerateSort(wSort, pf.Base)
+ */
/*
pf.appendUnique(wFind) // Append() enforce no unique keys
@@ -39,25 +232,34 @@ func (pb *Files) makeNewSortfile(pf *File) error {
pf.findFunc(wFind)
*/
- header(wFind, pf)
- pf.syncLock(wFind)
- pf.specialBases(wFind)
+ /*
+ wFind, _ := os.OpenFile(pf.Filebase+".find.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ defer wFind.Close()
+ header(wFind, pf)
+ pf.specialBases(wFind)
- // attempt to add sort functions for pf.Base
- if err := pf.processMessage(pf.Bases, wSort, wFind); err != nil {
- return err
- }
- if err := pf.processMessage(pf.Base, wSort, wFind); err != nil {
- return err
- }
+ // attempt to add sort functions for pf.Base
+ if err := pf.processMessage(pf.Bases, wSort, wFind); err != nil {
+ return err
+ }
+ if err := pf.processMessage(pf.Base, wSort, wFind); err != nil {
+ return err
+ }
+ */
return nil
}
-func (pf *File) newGenerateSort(w io.Writer, parent *MsgName) error {
+/*
+func addIterNew(w io.Write, msg *MsgName {
var FRUIT string = parent.Name
var LOCK string = parent.Lockname
+ newIter(w, FRUIT, APPLE, APPLES, LOCK)
+}
+*/
- var allLen bool
+func (pf *File) newGenerateSort(w io.Writer, parent *MsgName) error {
+ var FRUIT string = parent.Name
+ var LOCK string = parent.Lockname
for _, v := range parent.Vars {
if !v.IsRepeated {
@@ -65,18 +267,24 @@ func (pf *File) newGenerateSort(w io.Writer, parent *MsgName) error {
}
var APPLES string = v.VarName
var APPLE string = v.VarType
- if !allLen {
- // only can run these once for now
- addAllFunc(w, FRUIT, APPLE, LOCK)
- addLenFunc(w, FRUIT, APPLES, LOCK)
- allLen = true
- }
- addSelectAll(w, FRUIT, APPLE, APPLES, LOCK)
- newIter(w, FRUIT, APPLE, APPLES, LOCK)
msg := pf.findMsg(APPLE)
if msg == nil {
return fmt.Errorf("failed to find struct %s", APPLE)
}
+ if msg.NeedIter {
+ parent.NeedIter = false
+ // only can run these once for now
+ log.Info("START")
+ log.Printf("Add all() FRUIT=%s APPLE=%s\n", FRUIT, APPLE)
+ // addAllFunc(w, FRUIT, APPLE, LOCK)
+ log.Printf("Add len() FRUIT=%s APPLES=%s\n", FRUIT, APPLES)
+ addLenFunc(w, FRUIT, APPLES, LOCK)
+ log.Printf("Add selectAll() FRUIT=%s APPLE=%s APPLES=%s\n", FRUIT, APPLE, APPLES)
+ addSelectAll(w, FRUIT, APPLE, APPLES, LOCK)
+ // newIter(w, FRUIT, APPLE, APPLES, LOCK)
+ log.Info("END")
+ }
+
for _, v := range msg.Vars {
if !v.HasSort {
continue
@@ -104,6 +312,16 @@ func (pf *File) findMsg(s string) *MsgName {
return nil
}
+func (pf *File) allMsg() []*MsgName {
+ var all []*MsgName
+ all = append(all, pf.Bases)
+ all = append(all, pf.Base)
+ for _, msg := range pf.MsgNames {
+ all = append(all, msg)
+ }
+ return all
+}
+
func (pf *File) specialBases(wFind io.Writer) {
var FRUIT string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name)
var APPLES string = cases.Title(language.English, cases.NoLower).String(pf.Bases.Name)
diff --git a/generateSort.go b/generateSort.go
index a710212..fd2291d 100644
--- a/generateSort.go
+++ b/generateSort.go
@@ -5,16 +5,11 @@ import (
"io"
)
-// only make one of these for each message in the protobuf file
-func newIter(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) {
- fmt.Fprintln(w, "// DEFINE THE ITERATOR. is unique to the "+APPLE+" protobuf message")
- fmt.Fprintln(w, "// itializes a new iterator.")
- fmt.Fprintln(w, "func New"+APPLE+"Iterator(things []*"+APPLE+") *"+APPLE+"Iterator {")
- fmt.Fprintln(w, " return &"+APPLE+"Iterator{things: things}")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
+func newIterAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string {
+ funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {"
+
fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs")
- fmt.Fprintln(w, "func (x *"+FRUIT+") all"+APPLES+"() []*"+APPLE+" {")
+ fmt.Fprintln(w, funcdef)
fmt.Fprintln(w, " "+LOCK+".RLock()")
fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
fmt.Fprintln(w, "")
@@ -28,6 +23,26 @@ func newIter(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) {
fmt.Fprintln(w, " return tmp")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
+
+ return funcdef
+}
+
+// only make one of these for each message in the protobuf file
+func newIter(w io.Writer, msg *MsgName) string {
+ if !msg.NeedIter {
+ return "iter already done for " + msg.Name
+ }
+ msg.NeedIter = false
+ APPLE := msg.Name
+
+ funcdef := "func New" + APPLE + "Iterator(things []*" + APPLE + ") *" + APPLE + "Iterator"
+
+ fmt.Fprintln(w, "// DEFINE THE", APPLE, "ITERATOR.")
+ fmt.Fprintln(w, "// itializes a new iterator.")
+ fmt.Fprintln(w, funcdef, "{")
+ fmt.Fprintln(w, " return &"+APPLE+"Iterator{things: things}")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+APPLE+"Iterator struct {")
fmt.Fprintln(w, " sync.RWMutex // this isn't getting used properly yet?")
fmt.Fprintln(w, "")
@@ -53,9 +68,28 @@ func newIter(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) {
fmt.Fprintln(w, "")
fmt.Fprintln(w, "// END DEFINE THE ITERATOR")
fmt.Fprintln(w, "")
+
+ return funcdef
+}
+
+// maybe there are better ways in GO now adays // that's fine though. this is easy to read
+// TODO; figure out what types this actually works on
+// TODO; add timestamppb compare
+func newSortType(w io.Writer, STRUCT, VARNAME string) string {
+ fmt.Fprintln(w, "// sort struct by", VARNAME)
+ fmt.Fprintln(w, "type "+STRUCT+VARNAME+" []*"+STRUCT+"")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "func (a "+STRUCT+VARNAME+") Len() int { return len(a) }")
+ fmt.Fprintln(w, "func (a "+STRUCT+VARNAME+") Less(i, j int) bool { return a[i]."+VARNAME+" < a[j]."+VARNAME+" }")
+ fmt.Fprintln(w, "func (a "+STRUCT+VARNAME+") Swap(i, j int) { a[i], a[j] = a[j], a[i] }")
+ fmt.Fprintln(w, "")
+
+ return "type " + STRUCT + VARNAME + " []*" + STRUCT + " // { return a[i]." + VARNAME + " < a[j]." + VARNAME + " }"
}
-func newSortBy(w io.Writer, FRUIT, APPLE, APPLES, COLOR string) {
+func newSortBy(w io.Writer, FRUIT, APPLE, APPLES, COLOR string) string {
+ funcdef := "func (x *" + FRUIT + ") SortBy" + COLOR + "() *" + APPLE + "Iterator // field: " + COLOR
+
fmt.Fprintln(w, "// START sort by ", COLOR, "(this is all you need once the Iterator is defined)")
fmt.Fprintln(w, "type "+APPLE+COLOR+" []*"+APPLE+"")
fmt.Fprintln(w, "")
@@ -72,32 +106,42 @@ func newSortBy(w io.Writer, FRUIT, APPLE, APPLES, COLOR string) {
fmt.Fprintln(w, " return iterator")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "// END sort by", COLOR)
+
+ return funcdef
}
-func addAllFunc(w io.Writer, FRUIT, APPLE, LOCK string) {
- fmt.Fprintln(w, "func (x *"+FRUIT+") All() *"+APPLE+"Iterator {")
- fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLE+"()")
+func addAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
+ funcdef := "func (x *" + FRUIT + ") All() *" + APPLE + "Iterator {"
+
+ fmt.Fprintln(w, funcdef)
+ fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " iterator := New"+APPLE+"Iterator("+APPLE+"Pointers)")
fmt.Fprintln(w, " return iterator")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
+
+ return funcdef
}
-func addLenFunc(w io.Writer, FRUIT, APPLES, LOCK string) {
+func addLenFunc(w io.Writer, FRUIT, APPLES, LOCK string) string {
+ funcdef := "func (x *" + FRUIT + ") Len() int {"
fmt.Fprintln(w, "")
- fmt.Fprintln(w, "func (x *"+FRUIT+") Len() int {")
+ fmt.Fprintln(w, funcdef)
fmt.Fprintln(w, " "+LOCK+".RLock()")
fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " return len(x."+APPLES+")")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
+
+ return funcdef
}
-func addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) {
+func addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) string {
+ funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE
fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs")
- fmt.Fprintln(w, "func (x *"+FRUIT+") selectAll"+APPLE+"() []*"+APPLE+" {")
+ fmt.Fprintln(w, funcdef, "{")
fmt.Fprintln(w, " "+LOCK+".RLock()")
fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
fmt.Fprintln(w, "")
@@ -110,4 +154,6 @@ func addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCK string) {
fmt.Fprintln(w, "")
fmt.Fprintln(w, " return tmp")
fmt.Fprintln(w, "}")
+
+ return funcdef
}
diff --git a/human.go b/human.go
index 0aebb80..c735bf4 100644
--- a/human.go
+++ b/human.go
@@ -1,11 +1,18 @@
package main
import (
+ "fmt"
+
"go.wit.com/log"
)
+// This was just going to be a function to print the results to stdout
+
+// instead, it's the core logic of the whole app
+// --dry-run on the command line will just print what would be generated
+
// print the protobuf in human form
-func (pf *File) printMsgTable() {
+func (pf *File) printMsgTable() error {
pf.Bases.printMsg()
pf.Base.printMsg()
@@ -13,6 +20,85 @@ func (pf *File) printMsgTable() {
for _, msg := range pf.MsgNames {
msg.printMsg()
}
+
+ log.Printf("\n")
+ log.Printf(" %-2s %20s %20s %20s %20s\n", "", "PARENT STRUCT", "VAR STRUCT TYPE", "VAR NAME", "LOCK")
+ // for i, s := range slices.Backward(pf.ToSort) {
+ for i, s := range pf.ToSort {
+ var funcname string
+ STRUCT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
+ LOCK := s.Lockname
+
+ log.Printf("SORT: %-2d %20s %20s %20s %20s %s\n", i, STRUCT, CHILD, VARNAME, LOCK, "")
+
+ var FUNCTYPE string
+ if STRUCT == VARNAME {
+ FUNCTYPE = STRUCT
+ } else {
+ FUNCTYPE = VARNAME
+ }
+
+ if s.VarType+"s" == s.VarName {
+ funcname = "func (x *" + FUNCTYPE + ") All() *[]iter" + s.VarType
+ } else {
+ funcname = "func (x *" + FUNCTYPE + ") all" + s.VarName + "() *[]iter" + s.VarType
+ }
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ msg := pf.findMsg(s.VarType)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
+ for _, v := range msg.Vars {
+ if v.HasSort {
+ funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+
+ var ucount int
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ ucount += 1
+ funcname := "func (x *" + FUNCTYPE + ") AppendUnique" + v.VarName + "(" + v.VarType + ")"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ funcname := "func (x *" + FUNCTYPE + ") DeleteBy" + v.VarName + "(" + v.VarType + ") bool"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+
+ for _, v := range msg.Vars {
+ if v.HasUnique {
+ funcname = "func (x *" + FUNCTYPE + ") FindBy" + v.VarName + "(a " + v.VarType + ") *" + s.VarType + "(using" + v.VarName + ")"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ } else {
+ if v.VarType == "string" {
+ funcname = "func (x *" + FUNCTYPE + ") FindBy" + v.VarName + "(a string) []*" + s.VarType + " ???"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ }
+ if ucount == 1 {
+ for _, v := range msg.Vars {
+ if !v.HasUnique {
+ continue
+ }
+ funcname = "func (x *" + FUNCTYPE + ") Insert(a *" + v.VarType + ") (*" + CHILD + ", isNew bool)"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ if ucount > 1 {
+ funcname = "func (x *" + FUNCTYPE + ") Insert(a *" + CHILD + ") (*" + CHILD + ", isNew bool)"
+ log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+
+ }
+ return nil
}
func (msg *MsgName) printMsg() {
diff --git a/main.go b/main.go
index 59d4ded..df6d00d 100644
--- a/main.go
+++ b/main.go
@@ -2,9 +2,10 @@
// +build go1.20
// protobuf the way I am using them, require GO 1.20. I think. I could be wrong.
+// The Go Protocol Buffers library embeds a sync.Mutex within the MessageState struct to prevent unintended shallow copies of message structs
+// this optionally (but it is the default) inserts a mutex into the struct generated by protoc
-// go:generate go-mod-clean
-// go:generate autogenpb auto.proto
+// go:generate autogenpb --proto file.proto
package main
@@ -25,6 +26,8 @@ import (
var VERSION string
var BUILDTIME string
+var fsort *os.File // the sort.pb.go output file
+
func main() {
pp := arg.MustParse(&argv)
@@ -51,6 +54,7 @@ func main() {
pf := new(File)
pb.Files = append(pb.Files, pf)
pf.Filename = argv.Proto
+ pf.IterMap = make(map[string]string)
pf.Filebase = strings.TrimSuffix(argv.Proto, ".proto")
@@ -69,6 +73,21 @@ func main() {
badExit(fmt.Errorf("Base was nil. 'message %s {` did not exist", pf.Filebase))
}
+ /*
+ // prep the output file
+ if !argv.DryRun {
+ var err error
+ fsort, err = os.OpenFile(pf.Filebase+".newsort.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ badExit(err)
+ }
+ defer fsort.Close()
+
+ header(fsort, pf)
+ pf.syncLock(fsort)
+ }
+ */
+
// show the protobuf of the protobuf. It's like Inception
pf.printMsgTable()
diff --git a/protoParse.go b/protoParse.go
index 8031785..2cefc80 100644
--- a/protoParse.go
+++ b/protoParse.go
@@ -56,15 +56,15 @@ func (pb *Files) hasPluralMessage(f *File) error {
return fmt.Errorf("proto file error %s", f.Filename)
}
-func (pb *Files) protoParse(f *File) error {
+func (pb *Files) protoParse(pf *File) error {
// does the file conform to the standard? (also reads in UUID & Version)
- if err := pb.hasPluralMessage(f); err != nil {
+ if err := pb.hasPluralMessage(pf); err != nil {
return err
}
- log.Info(f.Filename, "is valid so far")
+ log.Info(pf.Filename, "is valid so far")
// read in the .proto file
- data, err := os.ReadFile(f.Filename)
+ data, err := os.ReadFile(pf.Filename)
if err != nil {
return err
}
@@ -74,7 +74,7 @@ func (pb *Files) protoParse(f *File) error {
// parse the proto file for message struct names
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "message ") {
- curmsg = f.parseForMessage(line)
+ curmsg = pf.parseForMessage(line)
}
// this logic isn't right. find end of message with more bravado
if strings.HasPrefix(line, "}") {
@@ -93,6 +93,10 @@ func (pb *Files) protoParse(f *File) error {
// 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])
@@ -110,9 +114,40 @@ func (pb *Files) protoParse(f *File) error {
}
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, "//")
@@ -169,6 +204,7 @@ func (pf *File) parseForMessage(line string) *MsgName {
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