diff options
| author | Jeff Carr <[email protected]> | 2025-10-15 19:43:22 -0500 | 
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-10-15 19:43:22 -0500 | 
| commit | 30e8de23f6ae78136e93add8e1464da5e45b020e (patch) | |
| tree | 144ea63b3a3061a05d1ba45d63adfecba108532d | |
| parent | 0c6082d44c7fbf46d8d44d50972d9f3302414d5b (diff) | |
rename filesv0.5.26
| -rw-r--r-- | generate.go | 395 | ||||
| -rw-r--r-- | generateSort.go | 550 | ||||
| -rw-r--r-- | generateSortFuncs.go | 241 | 
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 +}  | 
