refactor again. I want to make this clean
as clean as possible because, I use this tool alot. everywhere. I want it to always work. I need do not want it to break
This commit is contained in:
parent
0d2dc9fb25
commit
cfd9ec5ccd
28
Makefile
28
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
20
file.proto
20
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
|
||||
|
|
276
generate.go
276
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,44 +232,59 @@ 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 addIterNew(w io.Write, msg *MsgName {
|
||||
var FRUIT string = parent.Name
|
||||
var LOCK string = parent.Lockname
|
||||
newIter(w, FRUIT, APPLE, APPLES, LOCK)
|
||||
}
|
||||
*/
|
||||
|
||||
func (pf *File) newGenerateSort(w io.Writer, parent *MsgName) error {
|
||||
var FRUIT string = parent.Name
|
||||
var LOCK string = parent.Lockname
|
||||
|
||||
var allLen bool
|
||||
|
||||
for _, v := range parent.Vars {
|
||||
if !v.IsRepeated {
|
||||
continue
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
func newSortBy(w io.Writer, FRUIT, APPLE, APPLES, COLOR string) {
|
||||
// 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) 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
|
||||
}
|
||||
|
|
88
human.go
88
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() {
|
||||
|
|
23
main.go
23
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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue