summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--generate.go395
-rw-r--r--generateSort.go550
-rw-r--r--generateSortFuncs.go241
3 files changed, 593 insertions, 593 deletions
diff --git a/generate.go b/generate.go
deleted file mode 100644
index f905d9d..0000000
--- a/generate.go
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
-// Use of this source code is governed by the GPL 3.0
-
-package main
-
-import (
- "fmt"
- "os"
-
- "go.wit.com/log"
-)
-
-// this file is named poorly. It has more than Sort()
-
-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()
-
- headerSort(wSort, pf)
- pf.syncLock(wSort)
- if os.Getenv("PROTOBUF_REGRET") != "true" {
- pf.addNewFunc(wSort)
- }
-
- fmt.Fprintf(wSort, "// START SORT\n")
- fmt.Fprintf(wSort, "\n")
-
- // add iterators for all the structs to be used
- for _, msg := range pf.allMsg() {
- funcdef := newScannerDefines(wSort, msg)
- log.Printf("Adding %s\n", funcdef)
- }
-
- // log.Printf("START COMPARE\n")
- for _, msg := range pf.allMsg() {
- PARENT := msg.Name
- for _, v := range msg.Vars {
- if !v.HasSort {
- continue
- }
- if v.IsRepeated {
- // can't work against slices
- continue
- }
- if v.VarType != "string" {
- continue
- }
- VARNAME := v.VarName
- funcdef := msg.newSortType(wSort, PARENT, VARNAME)
- log.Printf("Adding %s\n", funcdef)
- }
- }
-
- // add selectAll() functions for all the sort combinations that will be used
- for _, 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
-
- msg := pf.findMsg(s.MsgName)
- if msg == nil {
- return fmt.Errorf("failed to find struct %s", s.VarType)
- }
-
- funcdef := msg.newScannerAll(wSort, FRUIT, APPLE, APPLES, LOCK)
- log.Printf("Adding %s\n", funcdef)
- }
-
- // log.Printf("START SELECT\n")
- // make the sort iterators selectAll()
- for _, s := range pf.ToSort {
- PARENT := s.MsgName
- CHILD := s.VarType
- VARNAME := s.VarName
- LOCK := s.Lockname
-
- msg := pf.findMsg(s.MsgName)
- if msg == nil {
- return fmt.Errorf("failed to find struct %s", s.VarType)
- }
-
- funcdef := msg.addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK)
- log.Printf("Adding %s\n", funcdef)
- }
- // log.Printf("END SELECT\n")
-
- // log.Printf("START SORT\n")
- // make the SortBy() functions
- for _, s := range pf.ToSort {
- // var funcname string
- PARENT := s.MsgName
- VARNAME := s.VarName
-
- pmsg := pf.findMsg(s.MsgName)
- if pmsg == nil {
- return fmt.Errorf("failed to find struct %s", s.MsgName)
- }
-
- 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.IsRepeated {
- // can't work against slices
- continue
- }
- if v.HasSort {
- // funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType
- // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "fix", "", "", funcname)
- // funcdef := "func (x *"+FRUIT+") SortBy"+COLOR+"() *"+APPLE+"Iterator"
-
- if v.VarType == "string" {
- var sortby string
- // func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT string) string {
- if PARENT == VARNAME {
- sortby = "SortBy" + v.VarName
- sortname := "sort" + s.VarType + v.VarName
- selectName := "selectAll" + VARNAME
- funcdef := pmsg.newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName, v.VarName)
- log.Printf("Adding %s\n", funcdef)
-
- FRUITS := PARENT
- FRUIT := s.VarType
- SORTNAME := sortname
- BRAND := v.VarName
- funcdef = pmsg.addIterBy(wSort, FRUITS, FRUIT, BRAND, SORTNAME)
- log.Printf("Adding %s\n", funcdef)
-
- funcname := "Sort" + v.VarName
- STRUCT := PARENT
- LOCK := s.Lockname
- funcdef = pmsg.newSort(wSort, STRUCT, funcname, sortname, LOCK)
- log.Printf("Adding %s\n", funcdef)
- } else {
- // deprecate this THIS DOES NOT MAKE SENSE TO DO
- sortby = "Sort" + VARNAME + "By" + v.VarName
- }
- } else {
- // funcdef := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet"
- }
- }
- }
- }
-
- fmt.Fprintf(wSort, "\n")
- fmt.Fprintf(wSort, "// END SORT\n")
-
- // make Len() and Append()
- for _, msg := range pf.allMsg() {
- PARENT := msg.Name
- LOCK := msg.Lockname
-
- for _, v := range msg.Vars {
- if v.IsRepeated {
- VARNAME := v.VarName
- // funcdef := "func (x *" + PARENT + ") Len" + VARNAME + "() int " + CHILD + " name:" + VARNAME
-
- if PARENT == VARNAME {
- // special case
- funcdef := msg.addLenFunc(wSort, PARENT, VARNAME, LOCK) // + " " + v.VarType + " name:" + v.VarName
- funcdef += " # is special struct=varname"
- log.Printf("Adding %s\n", funcdef)
- }
- if PARENT == VARNAME {
- funcdef := msg.simpleAppend(wSort, PARENT, v.VarName, v.VarType)
- log.Printf("Adding %s\n", funcdef)
-
- funcdef = msg.simpleClone(wSort, PARENT, v.VarName, v.VarType)
- log.Printf("Adding %s\n", funcdef)
- }
- }
- }
- }
-
- // add All()
- for _, s := range pf.ToSort {
- PARENT := s.MsgName
- CHILD := s.VarType
- VARNAME := s.VarName
-
- // log.Printf("TO SORT IterAll() PARENT==VARNAME? PARENT=%s CHILD=%s VARNAME=%s (%v)\n", PARENT, CHILD, VARNAME, pf.ToSort)
- pmsg := pf.findMsg(PARENT)
- if pmsg == nil {
- // log.Printf("FAILED TO ADD SORT pmsg=nil PARENT=%s CHILD=%s VARNAME=%s\n", PARENT, CHILD, VARNAME)
- return fmt.Errorf("failed to find struct %s", s.MsgName)
- }
-
- if PARENT == VARNAME {
- funcdef := pmsg.addAllFunc(wSort, PARENT, CHILD, VARNAME)
- log.Printf("Adding %s\n", funcdef)
-
- FRUITS := PARENT
- FRUIT := CHILD
- funcdef = pmsg.addIterAll(wSort, FRUITS, FRUIT)
- log.Printf("Adding %s\n", funcdef)
- } else {
- // log.Printf("FAILED TO ADD SORT IterAll() PARENT != VARNAME PARENT=%s CHILD=%s VARNAME=%s\n", PARENT, CHILD, VARNAME)
- }
-
- /*
- // todo: figure out how to do more All() functions correction
- var FUNCTYPE string
- if PARENT == VARNAME {
- FUNCTYPE = PARENT
- } 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)
- */
- }
-
- // add Delete()
- for _, s := range pf.ToSort {
- PARENT := s.MsgName
- CHILD := s.VarType
- VARNAME := s.VarName
-
- pmsg := pf.findMsg(s.MsgName)
- if pmsg == nil {
- return fmt.Errorf("failed to find struct %s", s.MsgName)
- }
-
- if PARENT == VARNAME {
- funcdef := pmsg.addDeleteFunc(wSort, PARENT, VARNAME, CHILD)
- log.Printf("Adding %s\n", funcdef)
- }
- }
-
- // add Find() Delete() Insert()
- for _, s := range pf.ToSort {
- PARENT := s.MsgName
- VARNAME := s.VarName
-
- if PARENT != VARNAME {
- // this does not conform to the autogenpb standard format
- continue
- }
- // special case because of the enforced .proto format // ONLY SUPPORT THIS
-
- pmsg := pf.findMsg(s.MsgName)
- if pmsg == nil {
- return fmt.Errorf("failed to find struct %s", s.MsgName)
- }
-
- msg := pf.findMsg(s.VarType)
- if msg == nil {
- return fmt.Errorf("failed to find struct %s", s.VarType)
- }
-
- // find()
- for _, v := range msg.Vars {
- if !(v.VarType == "string" || (v.VarType == "int64")) {
- continue
- }
- if v.IsRepeated {
- continue
- }
- if v.HasUnique {
- // funcname = "func (x *" + PARENT + ") Find" + VARNAME + "By" + v.VarName + "(a " + v.VarType + ") *" + s.VarType + "(using" + v.VarName + ")"
- // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
- var FUNCNAME string
- if PARENT == VARNAME {
- // special case because of the enforced .proto format
- FUNCNAME = "FindBy" + v.VarName
- funcdef := pmsg.generateFindBy(wSort, FUNCNAME, PARENT, s, v)
- log.Printf("Adding %s\n", funcdef)
-
- FRUITS := PARENT
- FRUIT := s.VarType
- APPLE := v.VarName
- COLOR := v.VarType
- funcdef = pmsg.insertBy(wSort, FRUITS, FRUIT, APPLE, COLOR)
- log.Printf("Adding %s\n", funcdef)
- }
- } else {
- if v.VarType == "string" {
- // probably dumb. move to a database if you need this
- // funcname = "func (x *" + PARENT + ") Find" + VARNAME + "By" + v.VarName + "(a string) []*" + s.VarType + " ???"
- // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
- }
- }
- }
-
- // delete() functions
- for _, v := range msg.Vars {
- if v.VarType != "string" {
- continue
- }
- if v.IsRepeated {
- continue
- }
- if !v.HasUnique {
- continue
- }
- // funcname := "func (x *" + PARENT + ") Delete" + VARNAME + "By" + v.VarName + "(" + v.VarType + ") bool"
- // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
- FRUIT := PARENT
- APPLES := VARNAME
- APPLE := v.VarName
- COLOR := v.VarType
- var FUNCNAME string
- if PARENT == VARNAME {
- // special case because of the enforced .proto format // ONLY USE CASE THAT MAKES SENSE
- FUNCNAME = "DeleteBy" + v.VarName
- var funcdef string
- if argv.Delete {
- funcdef = pmsg.deleteByWithCopy(wSort, FRUIT, APPLES, APPLE, COLOR, FUNCNAME, v.VarName)
- } else {
- funcdef = pmsg.deleteBy(wSort, FRUIT, APPLES, APPLE, COLOR, FUNCNAME, v.VarName)
- }
- log.Printf("Adding %s\n", funcdef)
- } else {
- // deprecate these
- FUNCNAME = "Delete" + VARNAME + "By" + v.VarName
- }
- }
-
- // AppendBy() functions. todo: make Insert() for unique
- var ucount int
- for _, v := range msg.Vars {
- if v.VarType != "string" {
- continue
- }
- if v.IsRepeated {
- continue
- }
- if !v.HasUnique {
- continue
- }
- ucount += 1
- var FUNCNAME string
- if PARENT == VARNAME {
- // special case because of the enforced .proto format // ONLY SUPPORT THIS
- FUNCNAME = "AppendBy" + v.VarName
- funcdef := pmsg.simpleAppendBy(wSort, PARENT, FUNCNAME, VARNAME, v.VarName, s.VarType)
- log.Printf("Adding %s\n", funcdef)
-
- FUNCNAME = "CloneBy" + v.VarName
- funcdef = pmsg.simpleCloneBy(wSort, PARENT, FUNCNAME, VARNAME, v.VarName, s.VarType)
- log.Printf("Adding %s\n", funcdef)
- }
- }
-
- // TODO: do this next // x *Repos) InsertPath( string) *Repo // returns existing record or new record if path != exists
- if ucount == 1 {
- for _, v := range msg.Vars {
- if !v.HasUnique {
- continue
- }
- //funcname = "func (x *" + PARENT + ") Insert(a *" + v.VarType + ") (*" + CHILD + ", isNew bool) // todo"
- //log.Printf("%20s %s\n", "", funcdef)
- }
- }
- if ucount > 1 {
- //funcname = "func (x *" + PARENT + ") Insert(a *" + CHILD + ") (*" + CHILD + ", isNew bool) // todo"
- //log.Printf("%20s %s\n", "", funcdef)
- }
- }
- return nil
-}
-
-func (pf *File) findMsg(s string) *MsgName {
- if pf.Bases.Name == s {
- return pf.Bases
- }
- if pf.Base.Name == s {
- return pf.Base
- }
- for _, msg := range pf.MsgNames {
- if msg.Name == s {
- return msg
- }
- }
- 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
-}
diff --git a/generateSort.go b/generateSort.go
index 305896e..f905d9d 100644
--- a/generateSort.go
+++ b/generateSort.go
@@ -5,237 +5,391 @@ package main
import (
"fmt"
- "io"
+ "os"
+
+ "go.wit.com/log"
)
-func (msg *MsgName) newScannerAll(w io.Writer, FRUIT, APPLE, APPLES, LOCKold string) string {
- LOCK := msg.getLockname("x")
+// this file is named poorly. It has more than Sort()
- funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {"
+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()
- fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs")
- fmt.Fprintln(w, funcdef)
- fmt.Fprintln(w, " "+LOCK+".RLock()")
- fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " // Create a new slice to hold pointers to each FRUIT")
- fmt.Fprintln(w, " var tmp []*"+APPLE+"")
- fmt.Fprintln(w, " tmp = make([]*"+APPLE+", len(x."+APPLES+"))")
- fmt.Fprintln(w, " for i, p := range x."+APPLES+" {")
- fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " return tmp")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
+ headerSort(wSort, pf)
+ pf.syncLock(wSort)
+ if os.Getenv("PROTOBUF_REGRET") != "true" {
+ pf.addNewFunc(wSort)
+ }
- return funcdef
-}
+ fmt.Fprintf(wSort, "// START SORT\n")
+ fmt.Fprintf(wSort, "\n")
-// only make one of these for each message in the protobuf file
-func newScannerDefines(w io.Writer, msg *MsgName) string {
- if !msg.NeedIter {
- return "iter already done for " + msg.Name
+ // add iterators for all the structs to be used
+ for _, msg := range pf.allMsg() {
+ funcdef := newScannerDefines(wSort, msg)
+ log.Printf("Adding %s\n", funcdef)
}
- msg.NeedIter = false
- APPLE := msg.Name
- // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
- // in this file where it is "new or "New". I changed it to lower case 2025.01.12
- funcdef := "func new" + APPLE + "Scanner(things []*" + APPLE + ") *" + APPLE + "Scanner"
+ // log.Printf("START COMPARE\n")
+ for _, msg := range pf.allMsg() {
+ PARENT := msg.Name
+ for _, v := range msg.Vars {
+ if !v.HasSort {
+ continue
+ }
+ if v.IsRepeated {
+ // can't work against slices
+ continue
+ }
+ if v.VarType != "string" {
+ continue
+ }
+ VARNAME := v.VarName
+ funcdef := msg.newSortType(wSort, PARENT, VARNAME)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ }
- fmt.Fprintln(w, "// DEFINE THE", APPLE, "SCANNER.")
- fmt.Fprintln(w, "// itializes a new scanner.")
- fmt.Fprintln(w, funcdef, "{")
- fmt.Fprintln(w, " return &"+APPLE+"Scanner{things: things}")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "type "+APPLE+"Scanner struct {")
- fmt.Fprintln(w, " sync.Mutex")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " things []*"+APPLE+"")
- fmt.Fprintln(w, " index int")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "func (it *"+APPLE+"Scanner) Scan() bool {")
- fmt.Fprintln(w, " if it.index >= len(it.things) {")
- fmt.Fprintln(w, " return false")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " it.Lock()")
- fmt.Fprintln(w, " it.index++")
- fmt.Fprintln(w, " it.Unlock()")
- fmt.Fprintln(w, " return true")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "// Next() returns the next thing in the array")
- fmt.Fprintln(w, "func (it *"+APPLE+"Scanner) Next() *"+APPLE+" {")
- fmt.Fprintln(w, " if it.things[it.index-1] == nil {")
- fmt.Fprintln(w, " fmt.Println(\"Next() error in "+APPLE+"Scanner\", it.index)")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " return it.things[it.index-1]")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "// END DEFINE THE SCANNER")
- fmt.Fprintln(w, "")
+ // add selectAll() functions for all the sort combinations that will be used
+ for _, 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
- return funcdef
-}
+ msg := pf.findMsg(s.MsgName)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
-// 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 (msg *MsgName) newSortType(w io.Writer, STRUCT, VARNAME string) string {
- SORTNAME := "sort" + STRUCT + VARNAME
+ funcdef := msg.newScannerAll(wSort, FRUIT, APPLE, APPLES, LOCK)
+ log.Printf("Adding %s\n", funcdef)
+ }
- // Can these be lower case? Should they be lower case? maybe sort.Sort() requires upper case?
- fmt.Fprintln(w, "// sort struct by", VARNAME)
- fmt.Fprintln(w, "type "+SORTNAME+" []*"+STRUCT+"")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "func (a "+SORTNAME+") Len() int { return len(a) }")
- fmt.Fprintln(w, "func (a "+SORTNAME+") Less(i, j int) bool { return a[i]."+VARNAME+" < a[j]."+VARNAME+" }")
- fmt.Fprintln(w, "func (a "+SORTNAME+") Swap(i, j int) { a[i], a[j] = a[j], a[i] }")
- fmt.Fprintln(w, "")
+ // log.Printf("START SELECT\n")
+ // make the sort iterators selectAll()
+ for _, s := range pf.ToSort {
+ PARENT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
+ LOCK := s.Lockname
- return "type " + STRUCT + VARNAME + " []*" + STRUCT + " // { return a[i]." + VARNAME + " < a[j]." + VARNAME + " }"
-}
+ msg := pf.findMsg(s.MsgName)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
-// provdes a sorted iter. Does not modify the protobuf
-func (msg *MsgName) newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT, VARNAME string) string {
- funcdef := "func (x *" + STRUCT + ") " + SORTBY + "() *" + ITER + "Scanner"
+ funcdef := msg.addSelectAll(wSort, PARENT, CHILD, VARNAME, LOCK)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ // log.Printf("END SELECT\n")
- fmt.Fprintln(w, funcdef, "{")
- fmt.Fprintln(w, " // copy the pointers as fast as possible.")
- fmt.Fprintln(w, " things := x."+SELECT+"()")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "// todo: try slices.SortFunc() instead to see what happens")
- fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(things))")
- fmt.Fprintln(w, "// slices.SortFunc(things, func(a, b *"+STRUCT+") bool {")
- fmt.Fprintln(w, "// return a."+VARNAME+" < b."+VARNAME+" // Sort by ??. let the compiler work it out??")
- fmt.Fprintln(w, "// })")
- // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
- // in this file where it is "new or "New". I changed it to lower case 2025.01.12
- fmt.Fprintln(w, " return new"+ITER+"Scanner(things)")
- fmt.Fprintln(w, "}")
+ // log.Printf("START SORT\n")
+ // make the SortBy() functions
+ for _, s := range pf.ToSort {
+ // var funcname string
+ PARENT := s.MsgName
+ VARNAME := s.VarName
- return funcdef
-}
+ pmsg := pf.findMsg(s.MsgName)
+ if pmsg == nil {
+ return fmt.Errorf("failed to find struct %s", s.MsgName)
+ }
-// sorts the protobuf in place.
-func (msg *MsgName) newSort(w io.Writer, STRUCT, FUNCNAME, SORTNAME, LOCK string) string {
- funcdef := "func (pb *" + STRUCT + ") " + FUNCNAME + "() "
+ msg := pf.findMsg(s.VarType)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
- fmt.Fprintln(w, funcdef, "{")
- fmt.Fprintln(w, " "+LOCK+".Lock()")
- fmt.Fprintln(w, " defer "+LOCK+".Unlock()")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(pb."+STRUCT+"))")
- fmt.Fprintln(w, "}")
+ for _, v := range msg.Vars {
+ if v.IsRepeated {
+ // can't work against slices
+ continue
+ }
+ if v.HasSort {
+ // funcname := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType
+ // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "fix", "", "", funcname)
+ // funcdef := "func (x *"+FRUIT+") SortBy"+COLOR+"() *"+APPLE+"Iterator"
- return funcdef
-}
+ if v.VarType == "string" {
+ var sortby string
+ // func newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT string) string {
+ if PARENT == VARNAME {
+ sortby = "SortBy" + v.VarName
+ sortname := "sort" + s.VarType + v.VarName
+ selectName := "selectAll" + VARNAME
+ funcdef := pmsg.newSortBy(wSort, PARENT, s.VarType, sortname, sortby, selectName, v.VarName)
+ log.Printf("Adding %s\n", funcdef)
-func (msg *MsgName) addIterAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
- funcdef := "func (x *" + FRUIT + ") All() *" + APPLE + "Scanner {"
+ FRUITS := PARENT
+ FRUIT := s.VarType
+ SORTNAME := sortname
+ BRAND := v.VarName
+ funcdef = pmsg.addIterBy(wSort, FRUITS, FRUIT, BRAND, SORTNAME)
+ log.Printf("Adding %s\n", funcdef)
- fmt.Fprintln(w, funcdef)
- fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
- fmt.Fprintln(w, "")
- // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places
- // in this file where it is "new or "New". I changed it to lower case 2025.01.12
- fmt.Fprintln(w, " scanner := new"+APPLE+"Scanner("+APPLE+"Pointers)")
- fmt.Fprintln(w, " return scanner")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
+ funcname := "Sort" + v.VarName
+ STRUCT := PARENT
+ LOCK := s.Lockname
+ funcdef = pmsg.newSort(wSort, STRUCT, funcname, sortname, LOCK)
+ log.Printf("Adding %s\n", funcdef)
+ } else {
+ // deprecate this THIS DOES NOT MAKE SENSE TO DO
+ sortby = "Sort" + VARNAME + "By" + v.VarName
+ }
+ } else {
+ // funcdef := "func (x *" + FUNCTYPE + ") SortBy" + v.VarName + "(" + v.VarType + ") *[]iter" + s.VarType + " # can not do this yet"
+ }
+ }
+ }
+ }
- return funcdef
-}
+ fmt.Fprintf(wSort, "\n")
+ fmt.Fprintf(wSort, "// END SORT\n")
-func (msg *MsgName) addIterBy(w io.Writer, FRUITS, FRUIT, APPLE, SORTNAME string) string {
- fmt.Fprintln(w, "// 'for x := range' syntax using the awesome golang 1.24 'iter'")
- fmt.Fprintln(w, "func (x *"+FRUITS+") IterBy"+APPLE+"() iter.Seq[*"+FRUIT+"] {")
- fmt.Fprintln(w, " items := x.selectAll"+FRUITS+"()")
- fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(items))")
- fmt.Fprintln(w, " // log.Println(\"Made Iter.Seq[] with length\", len(items))")
- fmt.Fprintln(w, " return func(yield func(*"+FRUIT+") bool) {")
- fmt.Fprintln(w, " for _, v := range items {")
- fmt.Fprintln(w, " if !yield(v) {")
- fmt.Fprintln(w, " return")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, "}")
+ // make Len() and Append()
+ for _, msg := range pf.allMsg() {
+ PARENT := msg.Name
+ LOCK := msg.Lockname
- return ""
-}
+ for _, v := range msg.Vars {
+ if v.IsRepeated {
+ VARNAME := v.VarName
+ // funcdef := "func (x *" + PARENT + ") Len" + VARNAME + "() int " + CHILD + " name:" + VARNAME
-func (msg *MsgName) addIterAll(w io.Writer, FRUITS, FRUIT string) string {
- funcdef := "func (x *" + FRUITS + ") IterAll() iter.Seq[*" + FRUIT + "] {"
- fmt.Fprintln(w, "// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter'")
- fmt.Fprintln(w, funcdef)
- fmt.Fprintln(w, " items := x.selectAll"+FRUITS+"()")
- fmt.Fprintln(w, " // log.Println(\"Made All() Iter.Seq[] with length\", len(items))")
- fmt.Fprintln(w, " return func(yield func(*"+FRUIT+") bool) {")
- fmt.Fprintln(w, " for _, v := range items {")
- fmt.Fprintln(w, " if !yield(v) {")
- fmt.Fprintln(w, " return")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, "}")
+ if PARENT == VARNAME {
+ // special case
+ funcdef := msg.addLenFunc(wSort, PARENT, VARNAME, LOCK) // + " " + v.VarType + " name:" + v.VarName
+ funcdef += " # is special struct=varname"
+ log.Printf("Adding %s\n", funcdef)
+ }
+ if PARENT == VARNAME {
+ funcdef := msg.simpleAppend(wSort, PARENT, v.VarName, v.VarType)
+ log.Printf("Adding %s\n", funcdef)
- return funcdef
-}
+ funcdef = msg.simpleClone(wSort, PARENT, v.VarName, v.VarType)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ }
+ }
+ }
-func (msg *MsgName) addAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
- funcdef := "func (x *" + FRUIT + ") All() *" + APPLE + "Scanner {"
+ // add All()
+ for _, s := range pf.ToSort {
+ PARENT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
- fmt.Fprintln(w, funcdef)
- fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
- fmt.Fprintln(w, "")
- // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places
- // in this file where it is "new or "New". I changed it to lower case 2025.01.12
- fmt.Fprintln(w, " scanner := new"+APPLE+"Scanner("+APPLE+"Pointers)")
- fmt.Fprintln(w, " return scanner")
- fmt.Fprintln(w, "}")
- fmt.Fprintln(w, "")
+ // log.Printf("TO SORT IterAll() PARENT==VARNAME? PARENT=%s CHILD=%s VARNAME=%s (%v)\n", PARENT, CHILD, VARNAME, pf.ToSort)
+ pmsg := pf.findMsg(PARENT)
+ if pmsg == nil {
+ // log.Printf("FAILED TO ADD SORT pmsg=nil PARENT=%s CHILD=%s VARNAME=%s\n", PARENT, CHILD, VARNAME)
+ return fmt.Errorf("failed to find struct %s", s.MsgName)
+ }
- return funcdef
-}
+ if PARENT == VARNAME {
+ funcdef := pmsg.addAllFunc(wSort, PARENT, CHILD, VARNAME)
+ log.Printf("Adding %s\n", funcdef)
-func (msg *MsgName) addLenFunc(w io.Writer, FRUIT, APPLES, LOCKold string) string {
- LOCK := msg.getLockname("x")
+ FRUITS := PARENT
+ FRUIT := CHILD
+ funcdef = pmsg.addIterAll(wSort, FRUITS, FRUIT)
+ log.Printf("Adding %s\n", funcdef)
+ } else {
+ // log.Printf("FAILED TO ADD SORT IterAll() PARENT != VARNAME PARENT=%s CHILD=%s VARNAME=%s\n", PARENT, CHILD, VARNAME)
+ }
- funcdef := "func (x *" + FRUIT + ") Len() int {"
- fmt.Fprintln(w, "")
- 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, "")
+ /*
+ // todo: figure out how to do more All() functions correction
+ var FUNCTYPE string
+ if PARENT == VARNAME {
+ FUNCTYPE = PARENT
+ } else {
+ FUNCTYPE = VARNAME
+ }
- return funcdef
-}
+ 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)
+ */
+ }
+
+ // add Delete()
+ for _, s := range pf.ToSort {
+ PARENT := s.MsgName
+ CHILD := s.VarType
+ VARNAME := s.VarName
-func (msg *MsgName) addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCKold string) string {
- LOCK := msg.getLockname("x")
+ pmsg := pf.findMsg(s.MsgName)
+ if pmsg == nil {
+ return fmt.Errorf("failed to find struct %s", s.MsgName)
+ }
- funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE
- fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs")
- fmt.Fprintln(w, funcdef, "{")
- fmt.Fprintln(w, " "+LOCK+".RLock()")
- fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " // Create a new slice to hold pointers to each "+APPLE+"")
- fmt.Fprintln(w, " var tmp []*"+APPLE+"")
- fmt.Fprintln(w, " tmp = make([]*"+APPLE+", len(x."+APPLES+"))")
- fmt.Fprintln(w, " for i, p := range x."+APPLES+" {")
- fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration")
- fmt.Fprintln(w, " }")
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, " return tmp")
- fmt.Fprintln(w, "}")
+ if PARENT == VARNAME {
+ funcdef := pmsg.addDeleteFunc(wSort, PARENT, VARNAME, CHILD)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ }
+
+ // add Find() Delete() Insert()
+ for _, s := range pf.ToSort {
+ PARENT := s.MsgName
+ VARNAME := s.VarName
+
+ if PARENT != VARNAME {
+ // this does not conform to the autogenpb standard format
+ continue
+ }
+ // special case because of the enforced .proto format // ONLY SUPPORT THIS
+
+ pmsg := pf.findMsg(s.MsgName)
+ if pmsg == nil {
+ return fmt.Errorf("failed to find struct %s", s.MsgName)
+ }
+
+ msg := pf.findMsg(s.VarType)
+ if msg == nil {
+ return fmt.Errorf("failed to find struct %s", s.VarType)
+ }
+
+ // find()
+ for _, v := range msg.Vars {
+ if !(v.VarType == "string" || (v.VarType == "int64")) {
+ continue
+ }
+ if v.IsRepeated {
+ continue
+ }
+ if v.HasUnique {
+ // funcname = "func (x *" + PARENT + ") Find" + VARNAME + "By" + v.VarName + "(a " + v.VarType + ") *" + s.VarType + "(using" + v.VarName + ")"
+ // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ var FUNCNAME string
+ if PARENT == VARNAME {
+ // special case because of the enforced .proto format
+ FUNCNAME = "FindBy" + v.VarName
+ funcdef := pmsg.generateFindBy(wSort, FUNCNAME, PARENT, s, v)
+ log.Printf("Adding %s\n", funcdef)
+
+ FRUITS := PARENT
+ FRUIT := s.VarType
+ APPLE := v.VarName
+ COLOR := v.VarType
+ funcdef = pmsg.insertBy(wSort, FRUITS, FRUIT, APPLE, COLOR)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ } else {
+ if v.VarType == "string" {
+ // probably dumb. move to a database if you need this
+ // funcname = "func (x *" + PARENT + ") Find" + VARNAME + "By" + v.VarName + "(a string) []*" + s.VarType + " ???"
+ // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ }
+ }
+ }
+
+ // delete() functions
+ for _, v := range msg.Vars {
+ if v.VarType != "string" {
+ continue
+ }
+ if v.IsRepeated {
+ continue
+ }
+ if !v.HasUnique {
+ continue
+ }
+ // funcname := "func (x *" + PARENT + ") Delete" + VARNAME + "By" + v.VarName + "(" + v.VarType + ") bool"
+ // log.Printf(" %-2s %20s %20s %20s %s %s\n", "", "", "", "", "", funcname)
+ FRUIT := PARENT
+ APPLES := VARNAME
+ APPLE := v.VarName
+ COLOR := v.VarType
+ var FUNCNAME string
+ if PARENT == VARNAME {
+ // special case because of the enforced .proto format // ONLY USE CASE THAT MAKES SENSE
+ FUNCNAME = "DeleteBy" + v.VarName
+ var funcdef string
+ if argv.Delete {
+ funcdef = pmsg.deleteByWithCopy(wSort, FRUIT, APPLES, APPLE, COLOR, FUNCNAME, v.VarName)
+ } else {
+ funcdef = pmsg.deleteBy(wSort, FRUIT, APPLES, APPLE, COLOR, FUNCNAME, v.VarName)
+ }
+ log.Printf("Adding %s\n", funcdef)
+ } else {
+ // deprecate these
+ FUNCNAME = "Delete" + VARNAME + "By" + v.VarName
+ }
+ }
+
+ // AppendBy() functions. todo: make Insert() for unique
+ var ucount int
+ for _, v := range msg.Vars {
+ if v.VarType != "string" {
+ continue
+ }
+ if v.IsRepeated {
+ continue
+ }
+ if !v.HasUnique {
+ continue
+ }
+ ucount += 1
+ var FUNCNAME string
+ if PARENT == VARNAME {
+ // special case because of the enforced .proto format // ONLY SUPPORT THIS
+ FUNCNAME = "AppendBy" + v.VarName
+ funcdef := pmsg.simpleAppendBy(wSort, PARENT, FUNCNAME, VARNAME, v.VarName, s.VarType)
+ log.Printf("Adding %s\n", funcdef)
+
+ FUNCNAME = "CloneBy" + v.VarName
+ funcdef = pmsg.simpleCloneBy(wSort, PARENT, FUNCNAME, VARNAME, v.VarName, s.VarType)
+ log.Printf("Adding %s\n", funcdef)
+ }
+ }
- return funcdef
+ // TODO: do this next // x *Repos) InsertPath( string) *Repo // returns existing record or new record if path != exists
+ if ucount == 1 {
+ for _, v := range msg.Vars {
+ if !v.HasUnique {
+ continue
+ }
+ //funcname = "func (x *" + PARENT + ") Insert(a *" + v.VarType + ") (*" + CHILD + ", isNew bool) // todo"
+ //log.Printf("%20s %s\n", "", funcdef)
+ }
+ }
+ if ucount > 1 {
+ //funcname = "func (x *" + PARENT + ") Insert(a *" + CHILD + ") (*" + CHILD + ", isNew bool) // todo"
+ //log.Printf("%20s %s\n", "", funcdef)
+ }
+ }
+ return nil
+}
+
+func (pf *File) findMsg(s string) *MsgName {
+ if pf.Bases.Name == s {
+ return pf.Bases
+ }
+ if pf.Base.Name == s {
+ return pf.Base
+ }
+ for _, msg := range pf.MsgNames {
+ if msg.Name == s {
+ return msg
+ }
+ }
+ 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
}
diff --git a/generateSortFuncs.go b/generateSortFuncs.go
new file mode 100644
index 0000000..305896e
--- /dev/null
+++ b/generateSortFuncs.go
@@ -0,0 +1,241 @@
+// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
+// Use of this source code is governed by the GPL 3.0
+
+package main
+
+import (
+ "fmt"
+ "io"
+)
+
+func (msg *MsgName) newScannerAll(w io.Writer, FRUIT, APPLE, APPLES, LOCKold string) string {
+ LOCK := msg.getLockname("x")
+
+ funcdef := "func (x *" + FRUIT + ") all" + APPLES + "() []*" + APPLE + " {"
+
+ fmt.Fprintln(w, "// safely returns a slice of pointers to the FRUIT protobufs")
+ fmt.Fprintln(w, funcdef)
+ fmt.Fprintln(w, " "+LOCK+".RLock()")
+ fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, " // Create a new slice to hold pointers to each FRUIT")
+ fmt.Fprintln(w, " var tmp []*"+APPLE+"")
+ fmt.Fprintln(w, " tmp = make([]*"+APPLE+", len(x."+APPLES+"))")
+ fmt.Fprintln(w, " for i, p := range x."+APPLES+" {")
+ fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, "")
+ 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 newScannerDefines(w io.Writer, msg *MsgName) string {
+ if !msg.NeedIter {
+ return "iter already done for " + msg.Name
+ }
+ msg.NeedIter = false
+ APPLE := msg.Name
+
+ // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
+ // in this file where it is "new or "New". I changed it to lower case 2025.01.12
+ funcdef := "func new" + APPLE + "Scanner(things []*" + APPLE + ") *" + APPLE + "Scanner"
+
+ fmt.Fprintln(w, "// DEFINE THE", APPLE, "SCANNER.")
+ fmt.Fprintln(w, "// itializes a new scanner.")
+ fmt.Fprintln(w, funcdef, "{")
+ fmt.Fprintln(w, " return &"+APPLE+"Scanner{things: things}")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "type "+APPLE+"Scanner struct {")
+ fmt.Fprintln(w, " sync.Mutex")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, " things []*"+APPLE+"")
+ fmt.Fprintln(w, " index int")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "func (it *"+APPLE+"Scanner) Scan() bool {")
+ fmt.Fprintln(w, " if it.index >= len(it.things) {")
+ fmt.Fprintln(w, " return false")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " it.Lock()")
+ fmt.Fprintln(w, " it.index++")
+ fmt.Fprintln(w, " it.Unlock()")
+ fmt.Fprintln(w, " return true")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "// Next() returns the next thing in the array")
+ fmt.Fprintln(w, "func (it *"+APPLE+"Scanner) Next() *"+APPLE+" {")
+ fmt.Fprintln(w, " if it.things[it.index-1] == nil {")
+ fmt.Fprintln(w, " fmt.Println(\"Next() error in "+APPLE+"Scanner\", it.index)")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " return it.things[it.index-1]")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "// END DEFINE THE SCANNER")
+ 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 (msg *MsgName) newSortType(w io.Writer, STRUCT, VARNAME string) string {
+ SORTNAME := "sort" + STRUCT + VARNAME
+
+ // Can these be lower case? Should they be lower case? maybe sort.Sort() requires upper case?
+ fmt.Fprintln(w, "// sort struct by", VARNAME)
+ fmt.Fprintln(w, "type "+SORTNAME+" []*"+STRUCT+"")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "func (a "+SORTNAME+") Len() int { return len(a) }")
+ fmt.Fprintln(w, "func (a "+SORTNAME+") Less(i, j int) bool { return a[i]."+VARNAME+" < a[j]."+VARNAME+" }")
+ fmt.Fprintln(w, "func (a "+SORTNAME+") 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 + " }"
+}
+
+// provdes a sorted iter. Does not modify the protobuf
+func (msg *MsgName) newSortBy(w io.Writer, STRUCT, ITER, SORTNAME, SORTBY, SELECT, VARNAME string) string {
+ funcdef := "func (x *" + STRUCT + ") " + SORTBY + "() *" + ITER + "Scanner"
+
+ fmt.Fprintln(w, funcdef, "{")
+ fmt.Fprintln(w, " // copy the pointers as fast as possible.")
+ fmt.Fprintln(w, " things := x."+SELECT+"()")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "// todo: try slices.SortFunc() instead to see what happens")
+ fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(things))")
+ fmt.Fprintln(w, "// slices.SortFunc(things, func(a, b *"+STRUCT+") bool {")
+ fmt.Fprintln(w, "// return a."+VARNAME+" < b."+VARNAME+" // Sort by ??. let the compiler work it out??")
+ fmt.Fprintln(w, "// })")
+ // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here
+ // in this file where it is "new or "New". I changed it to lower case 2025.01.12
+ fmt.Fprintln(w, " return new"+ITER+"Scanner(things)")
+ fmt.Fprintln(w, "}")
+
+ return funcdef
+}
+
+// sorts the protobuf in place.
+func (msg *MsgName) newSort(w io.Writer, STRUCT, FUNCNAME, SORTNAME, LOCK string) string {
+ funcdef := "func (pb *" + STRUCT + ") " + FUNCNAME + "() "
+
+ fmt.Fprintln(w, funcdef, "{")
+ fmt.Fprintln(w, " "+LOCK+".Lock()")
+ fmt.Fprintln(w, " defer "+LOCK+".Unlock()")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(pb."+STRUCT+"))")
+ fmt.Fprintln(w, "}")
+
+ return funcdef
+}
+
+func (msg *MsgName) addIterAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
+ funcdef := "func (x *" + FRUIT + ") All() *" + APPLE + "Scanner {"
+
+ fmt.Fprintln(w, funcdef)
+ fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
+ fmt.Fprintln(w, "")
+ // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places
+ // in this file where it is "new or "New". I changed it to lower case 2025.01.12
+ fmt.Fprintln(w, " scanner := new"+APPLE+"Scanner("+APPLE+"Pointers)")
+ fmt.Fprintln(w, " return scanner")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+
+ return funcdef
+}
+
+func (msg *MsgName) addIterBy(w io.Writer, FRUITS, FRUIT, APPLE, SORTNAME string) string {
+ fmt.Fprintln(w, "// 'for x := range' syntax using the awesome golang 1.24 'iter'")
+ fmt.Fprintln(w, "func (x *"+FRUITS+") IterBy"+APPLE+"() iter.Seq[*"+FRUIT+"] {")
+ fmt.Fprintln(w, " items := x.selectAll"+FRUITS+"()")
+ fmt.Fprintln(w, " sort.Sort("+SORTNAME+"(items))")
+ fmt.Fprintln(w, " // log.Println(\"Made Iter.Seq[] with length\", len(items))")
+ fmt.Fprintln(w, " return func(yield func(*"+FRUIT+") bool) {")
+ fmt.Fprintln(w, " for _, v := range items {")
+ fmt.Fprintln(w, " if !yield(v) {")
+ fmt.Fprintln(w, " return")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, "}")
+
+ return ""
+}
+
+func (msg *MsgName) addIterAll(w io.Writer, FRUITS, FRUIT string) string {
+ funcdef := "func (x *" + FRUITS + ") IterAll() iter.Seq[*" + FRUIT + "] {"
+ fmt.Fprintln(w, "// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter'")
+ fmt.Fprintln(w, funcdef)
+ fmt.Fprintln(w, " items := x.selectAll"+FRUITS+"()")
+ fmt.Fprintln(w, " // log.Println(\"Made All() Iter.Seq[] with length\", len(items))")
+ fmt.Fprintln(w, " return func(yield func(*"+FRUIT+") bool) {")
+ fmt.Fprintln(w, " for _, v := range items {")
+ fmt.Fprintln(w, " if !yield(v) {")
+ fmt.Fprintln(w, " return")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, "}")
+
+ return funcdef
+}
+
+func (msg *MsgName) addAllFunc(w io.Writer, FRUIT, APPLE, APPLES string) string {
+ funcdef := "func (x *" + FRUIT + ") All() *" + APPLE + "Scanner {"
+
+ fmt.Fprintln(w, funcdef)
+ fmt.Fprintln(w, " "+APPLE+"Pointers := x.selectAll"+APPLES+"()")
+ fmt.Fprintln(w, "")
+ // should this be 'new' or 'New' ? Does it matter? I think it's totally internal here. I think there are only 3 places
+ // in this file where it is "new or "New". I changed it to lower case 2025.01.12
+ fmt.Fprintln(w, " scanner := new"+APPLE+"Scanner("+APPLE+"Pointers)")
+ fmt.Fprintln(w, " return scanner")
+ fmt.Fprintln(w, "}")
+ fmt.Fprintln(w, "")
+
+ return funcdef
+}
+
+func (msg *MsgName) addLenFunc(w io.Writer, FRUIT, APPLES, LOCKold string) string {
+ LOCK := msg.getLockname("x")
+
+ funcdef := "func (x *" + FRUIT + ") Len() int {"
+ fmt.Fprintln(w, "")
+ 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 (msg *MsgName) addSelectAll(w io.Writer, FRUIT, APPLE, APPLES, LOCKold string) string {
+ LOCK := msg.getLockname("x")
+
+ funcdef := "func (x *" + FRUIT + ") selectAll" + APPLES + "() []*" + APPLE
+ fmt.Fprintln(w, "// safely returns a slice of pointers to the "+APPLE+" protobufs")
+ fmt.Fprintln(w, funcdef, "{")
+ fmt.Fprintln(w, " "+LOCK+".RLock()")
+ fmt.Fprintln(w, " defer "+LOCK+".RUnlock()")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, " // Create a new slice to hold pointers to each "+APPLE+"")
+ fmt.Fprintln(w, " var tmp []*"+APPLE+"")
+ fmt.Fprintln(w, " tmp = make([]*"+APPLE+", len(x."+APPLES+"))")
+ fmt.Fprintln(w, " for i, p := range x."+APPLES+" {")
+ fmt.Fprintln(w, " tmp[i] = p // Copy pointers for safe iteration")
+ fmt.Fprintln(w, " }")
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, " return tmp")
+ fmt.Fprintln(w, "}")
+
+ return funcdef
+}