From 75f71fe3dbc6d4f066b66a3ebb8afa185a5d82e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Tue, 31 Oct 2023 22:58:28 +0100 Subject: [PATCH] v0.0.294 migrate bfcodegen to templates --- bfcodegen/_test_example.tgz | Bin 13313 -> 12084 bytes bfcodegen/csid-generate.go | 207 +++---------------------------- bfcodegen/csid-generate.template | 168 +++++++++++++++++++++++++ bfcodegen/csid-generate_test.go | 52 ++++++++ bfcodegen/enum-generate.go | 149 ++++------------------ bfcodegen/enum-generate.template | 97 +++++++++++++++ bfcodegen/enum-generate_test.go | 14 ++- bfcodegen/id-generate.go | 79 +++--------- bfcodegen/id-generate.template | 47 +++++++ bfcodegen/id-generate_test.go | 52 ++++++++ goextVersion.go | 4 +- 11 files changed, 492 insertions(+), 377 deletions(-) create mode 100644 bfcodegen/csid-generate.template create mode 100644 bfcodegen/csid-generate_test.go create mode 100644 bfcodegen/enum-generate.template create mode 100644 bfcodegen/id-generate.template create mode 100644 bfcodegen/id-generate_test.go diff --git a/bfcodegen/_test_example.tgz b/bfcodegen/_test_example.tgz index 500f74af4edaa87cce0ef07cda50013ea8db481f..a9acdf92f0b41c6554cbd7326fbc85a3a7f1aa6f 100644 GIT binary patch literal 12084 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
dr)GcjG+PNF8?b>E`otfNvCRKOxbc(-Obv6U0 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 literal 13313 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[A-Za-z0-9_]+)\s var rexCSIDChecksumConst = rext.W(regexp.MustCompile(`const ChecksumCharsetIDGenerator = "(?P[A-Za-z0-9_]*)"`)) +//go:embed csid-generate.template +var templateCSIDGenerateText string + func GenerateCharsetIDSpecs(sourceDir string, destFile string) error { files, err := os.ReadDir(sourceDir) @@ -168,198 +174,19 @@ func processCSIDFile(basedir string, fn string) ([]CSIDDef, string, error) { } func fmtCSIDOutput(cs string, ids []CSIDDef, pkgname string) string { - str := "// Code generated by id-generate.go DO NOT EDIT.\n" - str += "\n" - str += "package " + pkgname + "\n" - str += "\n" + templ := template.Must(template.New("csid-generate").Parse(templateCSIDGenerateText)) - str += `import "crypto/rand"` + "\n" - str += `import "fmt"` + "\n" - str += `import "github.com/go-playground/validator/v10"` + "\n" - str += `import "github.com/rs/zerolog/log"` + "\n" - str += `import "gogs.mikescher.com/BlackForestBytes/goext/exerr"` + "\n" - str += `import "gogs.mikescher.com/BlackForestBytes/goext/langext"` + "\n" - str += `import "gogs.mikescher.com/BlackForestBytes/goext/rext"` + "\n" - str += `import "math/big"` + "\n" - str += `import "reflect"` + "\n" - str += `import "regexp"` + "\n" - str += `import "strings"` + "\n" - str += "\n" - - str += "const ChecksumCharsetIDGenerator = \"" + cs + "\" // GoExtVersion: " + goext.GoextVersion + "\n" - str += "\n" - - str += "const idlen = 24\n" - str += "\n" - str += "const checklen = 1\n" - str += "\n" - str += `const idCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"` + "\n" - str += "const idCharsetLen = len(idCharset)\n" - str += "\n" - str += "var charSetReverseMap = generateCharsetMap()\n" - str += "\n" - str += "const (\n" - for _, iddef := range ids { - str += " prefix" + iddef.Name + " = \"" + iddef.Prefix + "\"" + "\n" - } - str += ")\n" - str += "\n" - str += "var (\n" - for _, iddef := range ids { - str += " regex" + iddef.Name + " = generateRegex(prefix" + iddef.Name + ")" + "\n" - } - str += ")\n" - str += "\n" - str += "func generateRegex(prefix string) rext.Regex {\n" - str += " return rext.W(regexp.MustCompile(fmt.Sprintf(\"^%s[%s]{%d}[%s]{%d}$\", prefix, idCharset, idlen-len(prefix)-checklen, idCharset, checklen)))\n" - str += "}\n" - str += "\n" - - str += `func generateCharsetMap() []int {` + "\n" - str += ` result := make([]int, 128)` + "\n" - str += ` for i := 0; i < len(result); i++ {` + "\n" - str += ` result[i] = -1` + "\n" - str += ` }` + "\n" - str += ` for idx, chr := range idCharset {` + "\n" - str += ` result[int(chr)] = idx` + "\n" - str += ` }` + "\n" - str += ` return result` + "\n" - str += `}` + "\n" - str += "\n" - str += `func generateID(prefix string) string {` + "\n" - str += ` k := ""` + "\n" - str += ` max := big.NewInt(int64(idCharsetLen))` + "\n" - str += ` checksum := 0` + "\n" - str += ` for i := 0; i < idlen-len(prefix)-checklen; i++ {` + "\n" - str += ` v, err := rand.Int(rand.Reader, max)` + "\n" - str += ` if err != nil {` + "\n" - str += ` panic(err)` + "\n" - str += ` }` + "\n" - str += ` v64 := v.Int64()` + "\n" - str += ` k += string(idCharset[v64])` + "\n" - str += ` checksum = (checksum + int(v64)) % (idCharsetLen)` + "\n" - str += ` }` + "\n" - str += ` checkstr := string(idCharset[checksum%idCharsetLen])` + "\n" - str += ` return prefix + k + checkstr` + "\n" - str += `}` + "\n" - str += "\n" - str += `func validateID(prefix string, value string) error {` + "\n" - str += ` if len(value) != idlen {` + "\n" - str += ` return exerr.New(exerr.TypeInvalidCSID, "id has the wrong length").Str("value", value).Build()` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` if !strings.HasPrefix(value, prefix) {` + "\n" - str += ` return exerr.New(exerr.TypeInvalidCSID, "id is missing the correct prefix").Str("value", value).Str("prefix", prefix).Build()` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` checksum := 0` + "\n" - str += ` for i := len(prefix); i < len(value)-checklen; i++ {` + "\n" - str += ` ichr := int(value[i])` + "\n" - str += ` if ichr < 0 || ichr >= len(charSetReverseMap) || charSetReverseMap[ichr] == -1 {` + "\n" - str += ` return exerr.New(exerr.TypeInvalidCSID, "id contains invalid characters").Str("value", value).Build()` + "\n" - str += ` }` + "\n" - str += ` checksum = (checksum + charSetReverseMap[ichr]) % (idCharsetLen)` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` checkstr := string(idCharset[checksum%idCharsetLen])` + "\n" - str += "\n" - str += ` if !strings.HasSuffix(value, checkstr) {` + "\n" - str += ` return exerr.New(exerr.TypeInvalidCSID, "id checkstring is invalid").Str("value", value).Str("checkstr", checkstr).Build()` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` return nil` + "\n" - str += `}` + "\n" - str += "\n" - str += `func getRawData(prefix string, value string) string {` + "\n" - str += ` if len(value) != idlen {` + "\n" - str += ` return ""` + "\n" - str += ` }` + "\n" - str += ` return value[len(prefix) : idlen-checklen]` + "\n" - str += `}` + "\n" - str += "\n" - str += `func getCheckString(prefix string, value string) string {` + "\n" - str += ` if len(value) != idlen {` + "\n" - str += ` return ""` + "\n" - str += ` }` + "\n" - str += ` return value[idlen-checklen:]` + "\n" - str += `}` + "\n" - str += "\n" - str += `func ValidateEntityID(vfl validator.FieldLevel) bool {` + "\n" - str += ` if !vfl.Field().CanInterface() {` + "\n" - str += ` log.Error().Msgf("Failed to validate EntityID (cannot interface ?!?)")` + "\n" - str += ` return false` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` ifvalue := vfl.Field().Interface()` + "\n" - str += "\n" - str += ` if value1, ok := ifvalue.(EntityID); ok {` + "\n" - str += "\n" - str += ` if vfl.Field().Type().Kind() == reflect.Pointer && langext.IsNil(value1) {` + "\n" - str += ` return true` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` if err := value1.Valid(); err != nil {` + "\n" - str += ` log.Debug().Msgf("Failed to validate EntityID '%s' (%s)", value1.String(), err.Error())` + "\n" - str += ` return false` + "\n" - str += ` } else {` + "\n" - str += ` return true` + "\n" - str += ` }` + "\n" - str += "\n" - str += ` } else {` + "\n" - str += ` log.Error().Msgf("Failed to validate EntityID (wrong type: %T)", ifvalue)` + "\n" - str += ` return false` + "\n" - str += ` }` + "\n" - str += `}` + "\n" - str += "\n" - - for _, iddef := range ids { - - str += "// ================================ " + iddef.Name + " (" + iddef.FileRelative + ") ================================" + "\n" - str += "" + "\n" - - str += "func New" + iddef.Name + "() " + iddef.Name + " {" + "\n" - str += " return " + iddef.Name + "(generateID(prefix" + iddef.Name + "))" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (id " + iddef.Name + ") Valid() error {" + "\n" - str += " return validateID(prefix" + iddef.Name + ", string(id))" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (i " + iddef.Name + ") String() string {" + "\n" - str += " return string(i)" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (i " + iddef.Name + ") Prefix() string {" + "\n" - str += " return prefix" + iddef.Name + "" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (id " + iddef.Name + ") Raw() string {" + "\n" - str += " return getRawData(prefix" + iddef.Name + ", string(id))" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (id " + iddef.Name + ") CheckString() string {" + "\n" - str += " return getCheckString(prefix" + iddef.Name + ", string(id))" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (id " + iddef.Name + ") Regex() rext.Regex {" + "\n" - str += " return regex" + iddef.Name + "" + "\n" - str += "}" + "\n" - - str += "" + "\n" + buffer := bytes.Buffer{} + err := templ.Execute(&buffer, langext.H{ + "PkgName": pkgname, + "Checksum": cs, + "GoextVersion": goext.GoextVersion, + "IDs": ids, + }) + if err != nil { + panic(err) } - return str + return buffer.String() } diff --git a/bfcodegen/csid-generate.template b/bfcodegen/csid-generate.template new file mode 100644 index 0000000..a512320 --- /dev/null +++ b/bfcodegen/csid-generate.template @@ -0,0 +1,168 @@ +// Code generated by csid-generate.go DO NOT EDIT. + +package {{.PkgName}} + +import "crypto/rand" +import "fmt" +import "github.com/go-playground/validator/v10" +import "github.com/rs/zerolog/log" +import "gogs.mikescher.com/BlackForestBytes/goext/exerr" +import "gogs.mikescher.com/BlackForestBytes/goext/langext" +import "gogs.mikescher.com/BlackForestBytes/goext/rext" +import "math/big" +import "reflect" +import "regexp" +import "strings" + +const ChecksumCharsetIDGenerator = "{{.Checksum}}" // GoExtVersion: {{.GoextVersion}} + +const idlen = 24 + +const checklen = 1 + +const idCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +const idCharsetLen = len(idCharset) + +var charSetReverseMap = generateCharsetMap() + +const ({{range .IDs}} + prefix{{.Name}} = "{{.Prefix}}" {{end}} +) + +var ({{range .IDs}} + regex{{.Name}} = generateRegex(prefix{{.Name}}) {{end}} +) + +func generateRegex(prefix string) rext.Regex { + return rext.W(regexp.MustCompile(fmt.Sprintf("^%s[%s]{%d}[%s]{%d}$", prefix, idCharset, idlen-len(prefix)-checklen, idCharset, checklen))) +} + +func generateCharsetMap() []int { + result := make([]int, 128) + for i := 0; i < len(result); i++ { + result[i] = -1 + } + for idx, chr := range idCharset { + result[int(chr)] = idx + } + return result +} + +func generateID(prefix string) string { + k := "" + csMax := big.NewInt(int64(idCharsetLen)) + checksum := 0 + for i := 0; i < idlen-len(prefix)-checklen; i++ { + v, err := rand.Int(rand.Reader, csMax) + if err != nil { + panic(err) + } + v64 := v.Int64() + k += string(idCharset[v64]) + checksum = (checksum + int(v64)) % (idCharsetLen) + } + checkstr := string(idCharset[checksum%idCharsetLen]) + return prefix + k + checkstr +} + +func validateID(prefix string, value string) error { + if len(value) != idlen { + return exerr.New(exerr.TypeInvalidCSID, "id has the wrong length").Str("value", value).Build() + } + + if !strings.HasPrefix(value, prefix) { + return exerr.New(exerr.TypeInvalidCSID, "id is missing the correct prefix").Str("value", value).Str("prefix", prefix).Build() + } + + checksum := 0 + for i := len(prefix); i < len(value)-checklen; i++ { + ichr := int(value[i]) + if ichr < 0 || ichr >= len(charSetReverseMap) || charSetReverseMap[ichr] == -1 { + return exerr.New(exerr.TypeInvalidCSID, "id contains invalid characters").Str("value", value).Build() + } + checksum = (checksum + charSetReverseMap[ichr]) % (idCharsetLen) + } + + checkstr := string(idCharset[checksum%idCharsetLen]) + + if !strings.HasSuffix(value, checkstr) { + return exerr.New(exerr.TypeInvalidCSID, "id checkstring is invalid").Str("value", value).Str("checkstr", checkstr).Build() + } + + return nil +} + +func getRawData(prefix string, value string) string { + if len(value) != idlen { + return "" + } + return value[len(prefix) : idlen-checklen] +} + +func getCheckString(prefix string, value string) string { + if len(value) != idlen { + return "" + } + return value[idlen-checklen:] +} + +func ValidateEntityID(vfl validator.FieldLevel) bool { + if !vfl.Field().CanInterface() { + log.Error().Msgf("Failed to validate EntityID (cannot interface ?!?)") + return false + } + + ifvalue := vfl.Field().Interface() + + if value1, ok := ifvalue.(EntityID); ok { + + if vfl.Field().Type().Kind() == reflect.Pointer && langext.IsNil(value1) { + return true + } + + if err := value1.Valid(); err != nil { + log.Debug().Msgf("Failed to validate EntityID '%s' (%s)", value1.String(), err.Error()) + return false + } else { + return true + } + + } else { + log.Error().Msgf("Failed to validate EntityID (wrong type: %T)", ifvalue) + return false + } +} + +{{range .IDs}} + +// ================================ {{.Name}} ({{.FileRelative}}) ================================ + +func New{{.Name}}() {{.Name}} { + return {{.Name}}(generateID(prefix{{.Name}})) +} + +func (id {{.Name}}) Valid() error { + return validateID(prefix{{.Name}}, string(id)) +} + +func (i {{.Name}}) String() string { + return string(i) +} + +func (i {{.Name}}) Prefix() string { + return prefix{{.Name}} +} + +func (id {{.Name}}) Raw() string { + return getRawData(prefix{{.Name}}, string(id)) +} + +func (id {{.Name}}) CheckString() string { + return getCheckString(prefix{{.Name}}, string(id)) +} + +func (id {{.Name}}) Regex() rext.Regex { + return regex{{.Name}} +} + +{{end}} \ No newline at end of file diff --git a/bfcodegen/csid-generate_test.go b/bfcodegen/csid-generate_test.go new file mode 100644 index 0000000..8f7c665 --- /dev/null +++ b/bfcodegen/csid-generate_test.go @@ -0,0 +1,52 @@ +package bfcodegen + +import ( + _ "embed" + "fmt" + "gogs.mikescher.com/BlackForestBytes/goext/cmdext" + "gogs.mikescher.com/BlackForestBytes/goext/langext" + "gogs.mikescher.com/BlackForestBytes/goext/tst" + "os" + "path/filepath" + "testing" + "time" +) + +//go:embed _test_example.tgz +var CSIDExampleModels []byte + +func TestGenerateCSIDSpecs(t *testing.T) { + + tmpFile := filepath.Join(t.TempDir(), langext.MustHexUUID()+".tgz") + + tmpDir := filepath.Join(t.TempDir(), langext.MustHexUUID()) + + err := os.WriteFile(tmpFile, CSIDExampleModels, 0o777) + tst.AssertNoErr(t, err) + + t.Cleanup(func() { _ = os.Remove(tmpFile) }) + + err = os.Mkdir(tmpDir, 0o777) + tst.AssertNoErr(t, err) + + t.Cleanup(func() { _ = os.RemoveAll(tmpFile) }) + + _, err = cmdext.Runner("tar").Arg("-xvzf").Arg(tmpFile).Arg("-C").Arg(tmpDir).FailOnExitCode().FailOnTimeout().Timeout(time.Minute).Run() + tst.AssertNoErr(t, err) + + err = GenerateCharsetIDSpecs(tmpDir, tmpDir+"/csid_gen.go") + tst.AssertNoErr(t, err) + + err = GenerateCharsetIDSpecs(tmpDir, tmpDir+"/csid_gen.go") + tst.AssertNoErr(t, err) + + fmt.Println() + fmt.Println() + fmt.Println() + fmt.Println("=====================================================================================================") + fmt.Println(string(tst.Must(os.ReadFile(tmpDir + "/csid_gen.go"))(t))) + fmt.Println("=====================================================================================================") + fmt.Println() + fmt.Println() + fmt.Println() +} diff --git a/bfcodegen/enum-generate.go b/bfcodegen/enum-generate.go index 6df552d..cee3c53 100644 --- a/bfcodegen/enum-generate.go +++ b/bfcodegen/enum-generate.go @@ -1,6 +1,8 @@ package bfcodegen import ( + "bytes" + _ "embed" "errors" "fmt" "gogs.mikescher.com/BlackForestBytes/goext" @@ -14,6 +16,7 @@ import ( "path/filepath" "regexp" "strings" + "text/template" "time" ) @@ -39,6 +42,9 @@ var rexEnumValueDef = rext.W(regexp.MustCompile(`^\s*(?P[A-Za-z0-9_]+)\s+( var rexEnumChecksumConst = rext.W(regexp.MustCompile(`const ChecksumEnumGenerator = "(?P[A-Za-z0-9_]*)"`)) +//go:embed enum-generate.template +var templateEnumGenerateText string + func GenerateEnumSpecs(sourceDir string, destFile string) error { files, err := os.ReadDir(sourceDir) @@ -204,133 +210,32 @@ func processEnumFile(basedir string, fn string) ([]EnumDef, string, error) { } func fmtEnumOutput(cs string, enums []EnumDef, pkgname string) string { - str := "// Code generated by enum-generate.go DO NOT EDIT.\n" - str += "\n" - str += "package " + pkgname + "\n" - str += "\n" - str += "import \"gogs.mikescher.com/BlackForestBytes/goext/langext\"" + "\n" - str += "import \"gogs.mikescher.com/BlackForestBytes/goext/enums\"" + "\n" - str += "\n" + templ := template.New("enum-generate") - str += "const ChecksumEnumGenerator = \"" + cs + "\" // GoExtVersion: " + goext.GoextVersion + "\n" - str += "\n" + templ = templ.Funcs(template.FuncMap{ + "boolToStr": func(b bool) string { return langext.Conditional(b, "true", "false") }, + "deref": func(v *string) string { return *v }, + "trimSpace": func(str string) string { return strings.TrimSpace(str) }, + "hasStr": func(v EnumDef) bool { return v.Type == "string" }, + "hasDescr": func(v EnumDef) bool { + return langext.ArrAll(v.Values, func(val EnumDefVal) bool { return val.Description != nil }) + }, + }) - for _, enumdef := range enums { + templ = template.Must(templ.Parse(templateEnumGenerateText)) - hasDescr := langext.ArrAll(enumdef.Values, func(val EnumDefVal) bool { return val.Description != nil }) - hasStr := enumdef.Type == "string" - - str += "// ================================ " + enumdef.EnumTypeName + " ================================" + "\n" - str += "//" + "\n" - str += "// File: " + enumdef.FileRelative + "\n" - str += "// StringEnum: " + langext.Conditional(hasStr, "true", "false") + "\n" - str += "// DescrEnum: " + langext.Conditional(hasDescr, "true", "false") + "\n" - str += "//" + "\n" - str += "" + "\n" - - str += "var __" + enumdef.EnumTypeName + "Values = []" + enumdef.EnumTypeName + "{" + "\n" - for _, v := range enumdef.Values { - str += " " + v.VarName + "," + "\n" - } - str += "}" + "\n" - str += "" + "\n" - - if hasDescr { - str += "var __" + enumdef.EnumTypeName + "Descriptions = map[" + enumdef.EnumTypeName + "]string{" + "\n" - for _, v := range enumdef.Values { - str += " " + v.VarName + ": \"" + strings.TrimSpace(*v.Description) + "\"," + "\n" - } - str += "}" + "\n" - str += "" + "\n" - } - - str += "var __" + enumdef.EnumTypeName + "Varnames = map[" + enumdef.EnumTypeName + "]string{" + "\n" - for _, v := range enumdef.Values { - str += " " + v.VarName + ": \"" + v.VarName + "\"," + "\n" - } - str += "}" + "\n" - str += "" + "\n" - - str += "func (e " + enumdef.EnumTypeName + ") Valid() bool {" + "\n" - str += " return langext.InArray(e, __" + enumdef.EnumTypeName + "Values)" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func (e " + enumdef.EnumTypeName + ") Values() []" + enumdef.EnumTypeName + " {" + "\n" - str += " return __" + enumdef.EnumTypeName + "Values" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func (e " + enumdef.EnumTypeName + ") ValuesAny() []any {" + "\n" - str += " return langext.ArrCastToAny(__" + enumdef.EnumTypeName + "Values)" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func (e " + enumdef.EnumTypeName + ") ValuesMeta() []enums.EnumMetaValue {" + "\n" - str += " return " + enumdef.EnumTypeName + "ValuesMeta()" - str += "}" + "\n" - str += "" + "\n" - - if hasStr { - str += "func (e " + enumdef.EnumTypeName + ") String() string {" + "\n" - str += " return string(e)" + "\n" - str += "}" + "\n" - str += "" + "\n" - } - - if hasDescr { - str += "func (e " + enumdef.EnumTypeName + ") Description() string {" + "\n" - str += " if d, ok := __" + enumdef.EnumTypeName + "Descriptions[e]; ok {" + "\n" - str += " return d" + "\n" - str += " }" + "\n" - str += " return \"\"" + "\n" - str += "}" + "\n" - str += "" + "\n" - } - - str += "func (e " + enumdef.EnumTypeName + ") VarName() string {" + "\n" - str += " if d, ok := __" + enumdef.EnumTypeName + "Varnames[e]; ok {" + "\n" - str += " return d" + "\n" - str += " }" + "\n" - str += " return \"\"" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func (e " + enumdef.EnumTypeName + ") Meta() enums.EnumMetaValue {" + "\n" - if hasDescr { - str += " return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: langext.Ptr(e.Description())}" - } else { - str += " return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: nil}" - } - str += "}" + "\n" - str += "" + "\n" - - str += "func Parse" + enumdef.EnumTypeName + "(vv string) (" + enumdef.EnumTypeName + ", bool) {" + "\n" - str += " for _, ev := range __" + enumdef.EnumTypeName + "Values {" + "\n" - str += " if string(ev) == vv {" + "\n" - str += " return ev, true" + "\n" - str += " }" + "\n" - str += " }" + "\n" - str += " return \"\", false" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func " + enumdef.EnumTypeName + "Values() []" + enumdef.EnumTypeName + " {" + "\n" - str += " return __" + enumdef.EnumTypeName + "Values" + "\n" - str += "}" + "\n" - str += "" + "\n" - - str += "func " + enumdef.EnumTypeName + "ValuesMeta() []enums.EnumMetaValue {" + "\n" - str += " return []enums.EnumMetaValue{" + "\n" - for _, v := range enumdef.Values { - str += " " + v.VarName + ".Meta(),\n" - } - str += " }" + "\n" - str += "}" + "\n" - str += "" + "\n" + buffer := bytes.Buffer{} + err := templ.Execute(&buffer, langext.H{ + "PkgName": pkgname, + "Checksum": cs, + "GoextVersion": goext.GoextVersion, + "Enums": enums, + }) + if err != nil { + panic(err) } - return str + return buffer.String() } diff --git a/bfcodegen/enum-generate.template b/bfcodegen/enum-generate.template new file mode 100644 index 0000000..11c3249 --- /dev/null +++ b/bfcodegen/enum-generate.template @@ -0,0 +1,97 @@ +// Code generated by enum-generate.go DO NOT EDIT. + +package {{.PkgName}} + +import "gogs.mikescher.com/BlackForestBytes/goext/langext" +import "gogs.mikescher.com/BlackForestBytes/goext/enums" + +const ChecksumEnumGenerator = "{{.Checksum}}" // GoExtVersion: {{.GoextVersion}} + +{{range .Enums}} + +{{ $hasStr := ( . | hasStr ) }} +{{ $hasDescr := ( . | hasDescr ) }} + +// ================================ {{.EnumTypeName}} ================================ +// +// File: {{.FileRelative}} +// StringEnum: {{$hasStr | boolToStr}} +// DescrEnum: {{$hasDescr | boolToStr}} +// + +var __{{.EnumTypeName}}Values = []{{.EnumTypeName}}{ {{range .Values}} + {{.VarName}}, {{end}} +} + +{{if $hasDescr}} +var __{{.EnumTypeName}}Descriptions = map[{{.EnumTypeName}}]string{ {{range .Values}} + {{.VarName}}: "{{.Description | deref | trimSpace}}", {{end}} +} +{{end}} + +var __{{.EnumTypeName}}Varnames = map[{{.EnumTypeName}}]string{ {{range .Values}} + {{.VarName}}: "{{.VarName}}", {{end}} +} + +func (e {{.EnumTypeName}}) Valid() bool { + return langext.InArray(e, __{{.EnumTypeName}}Values) +} + +func (e {{.EnumTypeName}}) Values() []{{.EnumTypeName}} { + return __{{.EnumTypeName}}Values +} + +func (e {{.EnumTypeName}}) ValuesAny() []any { + return langext.ArrCastToAny(__{{.EnumTypeName}}Values) +} + +func (e {{.EnumTypeName}}) ValuesMeta() []enums.EnumMetaValue { + return {{.EnumTypeName}}ValuesMeta() +} + +{{if $hasStr}} +func (e {{.EnumTypeName}}) String() string { + return string(e) +} +{{end}} + +{{if $hasDescr}} +func (e {{.EnumTypeName}}) Description() string { + if d, ok := __{{.EnumTypeName}}Descriptions[e]; ok { + return d + } + return "" +} +{{end}} + +func (e {{.EnumTypeName}}) VarName() string { + if d, ok := __{{.EnumTypeName}}Varnames[e]; ok { + return d + } + return "" +} + +func (e {{.EnumTypeName}}) Meta() enums.EnumMetaValue { + {{if $hasDescr}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: langext.Ptr(e.Description())} {{else}} return enums.EnumMetaValue{VarName: e.VarName(), Value: e, Description: nil} {{end}} +} + +func Parse{{.EnumTypeName}}(vv string) ({{.EnumTypeName}}, bool) { + for _, ev := range __{{.EnumTypeName}}Values { + if string(ev) == vv { + return ev, true + } + } + return "", false +} + +func {{.EnumTypeName}}Values() []{{.EnumTypeName}} { + return __{{.EnumTypeName}}Values +} + +func {{.EnumTypeName}}ValuesMeta() []enums.EnumMetaValue { + return []enums.EnumMetaValue{ {{range .Values}} + {{.VarName}}.Meta(), {{end}} + } +} + +{{end}} \ No newline at end of file diff --git a/bfcodegen/enum-generate_test.go b/bfcodegen/enum-generate_test.go index e92ae4c..72dcce7 100644 --- a/bfcodegen/enum-generate_test.go +++ b/bfcodegen/enum-generate_test.go @@ -2,6 +2,7 @@ package bfcodegen import ( _ "embed" + "fmt" "gogs.mikescher.com/BlackForestBytes/goext/cmdext" "gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/tst" @@ -12,7 +13,7 @@ import ( ) //go:embed _test_example.tgz -var ExampleModels []byte +var EnumExampleModels []byte func TestGenerateEnumSpecs(t *testing.T) { @@ -20,7 +21,7 @@ func TestGenerateEnumSpecs(t *testing.T) { tmpDir := filepath.Join(t.TempDir(), langext.MustHexUUID()) - err := os.WriteFile(tmpFile, ExampleModels, 0o777) + err := os.WriteFile(tmpFile, EnumExampleModels, 0o777) tst.AssertNoErr(t, err) t.Cleanup(func() { _ = os.Remove(tmpFile) }) @@ -39,4 +40,13 @@ func TestGenerateEnumSpecs(t *testing.T) { err = GenerateEnumSpecs(tmpDir, tmpDir+"/enums_gen.go") tst.AssertNoErr(t, err) + fmt.Println() + fmt.Println() + fmt.Println() + fmt.Println("=====================================================================================================") + fmt.Println(string(tst.Must(os.ReadFile(tmpDir + "/enums_gen.go"))(t))) + fmt.Println("=====================================================================================================") + fmt.Println() + fmt.Println() + fmt.Println() } diff --git a/bfcodegen/id-generate.go b/bfcodegen/id-generate.go index 700dfbb..951b579 100644 --- a/bfcodegen/id-generate.go +++ b/bfcodegen/id-generate.go @@ -1,6 +1,8 @@ package bfcodegen import ( + "bytes" + _ "embed" "errors" "fmt" "gogs.mikescher.com/BlackForestBytes/goext" @@ -14,6 +16,7 @@ import ( "path/filepath" "regexp" "strings" + "text/template" "time" ) @@ -29,6 +32,9 @@ var rexIDDef = rext.W(regexp.MustCompile(`^\s*type\s+(?P[A-Za-z0-9_]+)\s+s var rexIDChecksumConst = rext.W(regexp.MustCompile(`const ChecksumIDGenerator = "(?P[A-Za-z0-9_]*)"`)) +//go:embed id-generate.template +var templateIDGenerateText string + func GenerateIDSpecs(sourceDir string, destFile string) error { files, err := os.ReadDir(sourceDir) @@ -166,71 +172,22 @@ func processIDFile(basedir string, fn string) ([]IDDef, string, error) { } func fmtIDOutput(cs string, ids []IDDef, pkgname string) string { - str := "// Code generated by id-generate.go DO NOT EDIT.\n" - str += "\n" - str += "package " + pkgname + "\n" - str += "\n" + templ := template.Must(template.New("id-generate").Parse(templateIDGenerateText)) - str += "import \"go.mongodb.org/mongo-driver/bson\"" + "\n" - str += "import \"go.mongodb.org/mongo-driver/bson/bsontype\"" + "\n" - str += "import \"go.mongodb.org/mongo-driver/bson/primitive\"" + "\n" - str += "import \"gogs.mikescher.com/BlackForestBytes/goext/exerr\"" + "\n" - str += "\n" - - str += "const ChecksumIDGenerator = \"" + cs + "\" // GoExtVersion: " + goext.GoextVersion + "\n" - str += "\n" + buffer := bytes.Buffer{} anyDef := langext.ArrFirstOrNil(ids, func(def IDDef) bool { return def.Name == "AnyID" || def.Name == "AnyId" }) - for _, iddef := range ids { - - str += "// ================================ " + iddef.Name + " (" + iddef.FileRelative + ") ================================" + "\n" - str += "" + "\n" - - str += "func (i " + iddef.Name + ") MarshalBSONValue() (bsontype.Type, []byte, error) {" + "\n" - str += " if objId, err := primitive.ObjectIDFromHex(string(i)); err == nil {" + "\n" - str += " return bson.MarshalValue(objId)" + "\n" - str += " } else {" + "\n" - str += " return 0, nil, exerr.New(exerr.TypeMarshalEntityID, \"Failed to marshal " + iddef.Name + "(\"+i.String()+\") to ObjectId\").Str(\"value\", string(i)).Type(\"type\", i).Build()" + "\n" - str += " }" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (i " + iddef.Name + ") String() string {" + "\n" - str += " return string(i)" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (i " + iddef.Name + ") ObjID() (primitive.ObjectID, error) {" + "\n" - str += " return primitive.ObjectIDFromHex(string(i))" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - str += "func (i " + iddef.Name + ") Valid() bool {" + "\n" - str += " _, err := primitive.ObjectIDFromHex(string(i))" + "\n" - str += " return err == nil" + "\n" - str += "}" + "\n" - - str += "" + "\n" - - if anyDef != nil { - str += "func (i " + iddef.Name + ") AsAny() " + anyDef.Name + " {" + "\n" - str += " return " + anyDef.Name + "(i)" + "\n" - str += "}" + "\n" - - str += "" + "\n" - } - - str += "func New" + iddef.Name + "() " + iddef.Name + " {" + "\n" - str += " return " + iddef.Name + "(primitive.NewObjectID().Hex())" + "\n" - str += "}" + "\n" - - str += "" + "\n" - + err := templ.Execute(&buffer, langext.H{ + "PkgName": pkgname, + "Checksum": cs, + "GoextVersion": goext.GoextVersion, + "IDs": ids, + "AnyDef": anyDef, + }) + if err != nil { + panic(err) } - return str + return buffer.String() } diff --git a/bfcodegen/id-generate.template b/bfcodegen/id-generate.template new file mode 100644 index 0000000..7111fe4 --- /dev/null +++ b/bfcodegen/id-generate.template @@ -0,0 +1,47 @@ +// Code generated by id-generate.go DO NOT EDIT. + +package {{.PkgName}} + +import "go.mongodb.org/mongo-driver/bson" +import "go.mongodb.org/mongo-driver/bson/bsontype" +import "go.mongodb.org/mongo-driver/bson/primitive" +import "gogs.mikescher.com/BlackForestBytes/goext/exerr" + +const ChecksumIDGenerator = "{{.Checksum}}" // GoExtVersion: {{.GoextVersion}} + +{{range .IDs}} + +// ================================ {{.Name}} ({{.FileRelative}}) ================================ + +func (i {{.Name}}) MarshalBSONValue() (bsontype.Type, []byte, error) { + if objId, err := primitive.ObjectIDFromHex(string(i)); err == nil { + return bson.MarshalValue(objId) + } else { + return 0, nil, exerr.New(exerr.TypeMarshalEntityID, "Failed to marshal {{.Name}}("+i.String()+") to ObjectId").Str("value", string(i)).Type("type", i).Build() + } +} + +func (i {{.Name}}) String() string { + return string(i) +} + +func (i {{.Name}}) ObjID() (primitive.ObjectID, error) { + return primitive.ObjectIDFromHex(string(i)) +} + +func (i {{.Name}}) Valid() bool { + _, err := primitive.ObjectIDFromHex(string(i)) + return err == nil +} + +{{if ne $.AnyDef nil}} +func (i {{.Name}}) AsAny() {{$.AnyDef.Name}} { + return {{$.AnyDef.Name}}(i) +} +{{end}} + +func New{{.Name}}() {{.Name}} { + return {{.Name}}(primitive.NewObjectID().Hex()) +} + +{{end}} \ No newline at end of file diff --git a/bfcodegen/id-generate_test.go b/bfcodegen/id-generate_test.go new file mode 100644 index 0000000..f37b163 --- /dev/null +++ b/bfcodegen/id-generate_test.go @@ -0,0 +1,52 @@ +package bfcodegen + +import ( + _ "embed" + "fmt" + "gogs.mikescher.com/BlackForestBytes/goext/cmdext" + "gogs.mikescher.com/BlackForestBytes/goext/langext" + "gogs.mikescher.com/BlackForestBytes/goext/tst" + "os" + "path/filepath" + "testing" + "time" +) + +//go:embed _test_example.tgz +var IDExampleModels []byte + +func TestGenerateIDSpecs(t *testing.T) { + + tmpFile := filepath.Join(t.TempDir(), langext.MustHexUUID()+".tgz") + + tmpDir := filepath.Join(t.TempDir(), langext.MustHexUUID()) + + err := os.WriteFile(tmpFile, IDExampleModels, 0o777) + tst.AssertNoErr(t, err) + + t.Cleanup(func() { _ = os.Remove(tmpFile) }) + + err = os.Mkdir(tmpDir, 0o777) + tst.AssertNoErr(t, err) + + t.Cleanup(func() { _ = os.RemoveAll(tmpFile) }) + + _, err = cmdext.Runner("tar").Arg("-xvzf").Arg(tmpFile).Arg("-C").Arg(tmpDir).FailOnExitCode().FailOnTimeout().Timeout(time.Minute).Run() + tst.AssertNoErr(t, err) + + err = GenerateIDSpecs(tmpDir, tmpDir+"/id_gen.go") + tst.AssertNoErr(t, err) + + err = GenerateIDSpecs(tmpDir, tmpDir+"/id_gen.go") + tst.AssertNoErr(t, err) + + fmt.Println() + fmt.Println() + fmt.Println() + fmt.Println("=====================================================================================================") + fmt.Println(string(tst.Must(os.ReadFile(tmpDir + "/id_gen.go"))(t))) + fmt.Println("=====================================================================================================") + fmt.Println() + fmt.Println() + fmt.Println() +} diff --git a/goextVersion.go b/goextVersion.go index a134df4..1e16ad5 100644 --- a/goextVersion.go +++ b/goextVersion.go @@ -1,5 +1,5 @@ package goext -const GoextVersion = "0.0.293" +const GoextVersion = "0.0.294" -const GoextVersionTimestamp = "2023-10-30T13:37:31+0100" +const GoextVersionTimestamp = "2023-10-31T22:58:28+0100"