From bc24b100a9e3ef3c4271209e99c6ac57597446f3 Mon Sep 17 00:00:00 2001 From: Alex Bice Date: Wed, 3 Aug 2022 15:35:20 -0700 Subject: [PATCH] Add support for string enums (#124) * add support for string enums --- Makefile | 18 +- _example/strings_only.go | 6 + _example/strings_only_enum.go | 208 ++++++++++++++ _example/strings_only_test.go | 257 +++++++++++++++++ .../Test118CustomPrefixExampleFile-og | 204 ++++++++++++- generator/.snapshots/Test118ExampleFile-og | 108 ++++++- .../Test118ExampleFileMoreOptions-og | 122 +++++++- .../.snapshots/Test118NoPrefixExampleFile-og | 68 ++++- ...t118NoPrefixExampleFileWithSnakeToCamel-og | 68 ++++- .../.snapshots/TestCustomPrefixExampleFile | 204 ++++++++++++- generator/.snapshots/TestExampleFile | 108 ++++++- .../.snapshots/TestExampleFileMoreOptions | 122 +++++++- generator/.snapshots/TestNoPrefixExampleFile | 68 ++++- .../TestNoPrefixExampleFileWithSnakeToCamel | 68 ++++- generator/assets/assets.go | 25 +- generator/embedded.go | 2 +- generator/embedded_1.16.go | 2 +- generator/enum_string.tmpl | 268 ++++++++++++++++++ generator/example_test.go | 8 + generator/generator.go | 7 +- generator/generator_1.18_test.go | 2 +- generator/generator_test.go | 7 +- generator/template_funcs.go | 44 +++ go.mod | 1 + go.sum | 2 + 25 files changed, 1969 insertions(+), 28 deletions(-) create mode 100644 _example/strings_only.go create mode 100644 _example/strings_only_enum.go create mode 100644 _example/strings_only_test.go create mode 100644 generator/enum_string.tmpl diff --git a/Makefile b/Makefile index 30fdc956..930fd57d 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ deps: $(GOIMPORTS) PACKAGES='./generator' './_example' .PHONY: all -all: build fmt test example cover install +all: build fmt test example cover install assets build: deps $(GO) generate ./generator @@ -52,6 +52,7 @@ fmt: test: gen-test generate $(GO) test -v -race -coverprofile=coverage.out ./... + $(GO) test -v -race ./_example cover: gen-test test $(GO) tool cover -html=coverage.out -o coverage.html @@ -61,11 +62,11 @@ coveralls: $(GOVERALLS) $(GOVERALLS) -coverprofile=coverage.out -service=$(SERVICE) -repotoken=$(COVERALLS_TOKEN) clean: - $(GO) clean rm -f bin/go-enum rm -rf coverage/ rm -rf bin/ rm -rf dist/ + $(GO) clean .PHONY: assert-no-changes assert-no-changes: @@ -102,12 +103,15 @@ bin/goveralls: go.sum bin/go-bindata: go.sum $(call goinstall,github.com/kevinburke/go-bindata/go-bindata) -generate1_15: generator/assets/assets.go generator/enum.tmpl +assets: generator/enum.tmpl generator/enum_string.tmpl docker run -i -t -w /app -v $(shell pwd):/app --entrypoint /bin/sh golang:1.15 -c 'make clean $(GOBINDATA) && $(GO) generate ./generator && make clean' -.PHONY: snapshots1_18 -snapshots1_18: - docker run -i -t -w /app -v $(shell pwd):/app --entrypoint /bin/sh golang:1.18 -c './update-snapshots.sh || true && make clean && make' +snapshots: snapshots_1.17 +snapshots: snapshots_1.18 + +snapshots_%: + echo "##### updating snapshots for golang $* #####" + docker run -i -t -w /app -v $(shell pwd):/app --entrypoint /bin/sh golang:$* -c './update-snapshots.sh || true' .PHONY: ci ci: docker_1.14 @@ -118,4 +122,4 @@ ci: docker_1.18 docker_%: echo "##### testing golang $* #####" - docker run -i -t -w /app -v $(shell pwd):/app --entrypoint /bin/sh golang:$* -c 'make clean && make' + docker run -i -t -w /app -v $(shell pwd):/app --entrypoint /bin/sh golang:$* -c 'make clean && make' \ No newline at end of file diff --git a/_example/strings_only.go b/_example/strings_only.go new file mode 100644 index 00000000..2c7e7272 --- /dev/null +++ b/_example/strings_only.go @@ -0,0 +1,6 @@ +//go:generate ../bin/go-enum -f=$GOFILE --ptr --marshal --flag --nocase --mustparse --sqlnullstr --sql --names + +package example + +// ENUM(pending, running, completed, failed) +type StrState string diff --git a/_example/strings_only_enum.go b/_example/strings_only_enum.go new file mode 100644 index 00000000..ebaaa038 --- /dev/null +++ b/_example/strings_only_enum.go @@ -0,0 +1,208 @@ +// Code generated by go-enum DO NOT EDIT. +// Version: example +// Revision: example +// Build Date: example +// Built By: example + +package example + +import ( + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "strings" +) + +const ( + // StrStatePending is a StrState of type pending. + StrStatePending StrState = "pending" + // StrStateRunning is a StrState of type running. + StrStateRunning StrState = "running" + // StrStateCompleted is a StrState of type completed. + StrStateCompleted StrState = "completed" + // StrStateFailed is a StrState of type failed. + StrStateFailed StrState = "failed" +) + +var _StrStateNames = []string{ + string(StrStatePending), + string(StrStateRunning), + string(StrStateCompleted), + string(StrStateFailed), +} + +// StrStateNames returns a list of possible string values of StrState. +func StrStateNames() []string { + tmp := make([]string, len(_StrStateNames)) + copy(tmp, _StrStateNames) + return tmp +} + +// String implements the Stringer interface. +func (x StrState) String() string { + return string(x) +} + +// String implements the Stringer interface. +func (x StrState) IsValid() bool { + _, err := ParseStrState(string(x)) + return err == nil +} + +var _StrStateValue = map[string]StrState{ + "pending": StrStatePending, + "running": StrStateRunning, + "completed": StrStateCompleted, + "failed": StrStateFailed, +} + +// ParseStrState attempts to convert a string to a StrState. +func ParseStrState(name string) (StrState, error) { + if x, ok := _StrStateValue[name]; ok { + return x, nil + } + // Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to. + if x, ok := _StrStateValue[strings.ToLower(name)]; ok { + return x, nil + } + return StrState(""), fmt.Errorf("%s is not a valid StrState, try [%s]", name, strings.Join(_StrStateNames, ", ")) +} + +// MustParseStrState converts a string to a StrState, and panics if is not valid. +func MustParseStrState(name string) StrState { + val, err := ParseStrState(name) + if err != nil { + panic(err) + } + return val +} + +func (x StrState) Ptr() *StrState { + return &x +} + +// MarshalText implements the text marshaller method. +func (x StrState) MarshalText() ([]byte, error) { + return []byte(string(x)), nil +} + +// UnmarshalText implements the text unmarshaller method. +func (x *StrState) UnmarshalText(text []byte) error { + tmp, err := ParseStrState(string(text)) + if err != nil { + return err + } + *x = tmp + return nil +} + +var _StrStateErrNilPtr = errors.New("value pointer is nil") // one per type for package clashes + +// Scan implements the Scanner interface. +func (x *StrState) Scan(value interface{}) (err error) { + if value == nil { + *x = StrState("") + return + } + + // A wider range of scannable types. + // driver.Value values at the top of the list for expediency + switch v := value.(type) { + case string: + *x, err = ParseStrState(v) + case []byte: + *x, err = ParseStrState(string(v)) + case StrState: + *x = v + case *StrState: + if v == nil { + return _StrStateErrNilPtr + } + *x = *v + case *string: + if v == nil { + return _StrStateErrNilPtr + } + *x, err = ParseStrState(*v) + default: + return errors.New("invalid type for StrState") + } + + return +} + +// Value implements the driver Valuer interface. +func (x StrState) Value() (driver.Value, error) { + return x.String(), nil +} + +// Set implements the Golang flag.Value interface func. +func (x *StrState) Set(val string) error { + v, err := ParseStrState(val) + *x = v + return err +} + +// Get implements the Golang flag.Getter interface func. +func (x *StrState) Get() interface{} { + return *x +} + +// Type implements the github.com/spf13/pFlag Value interface. +func (x *StrState) Type() string { + return "StrState" +} + +type NullStrState struct { + StrState StrState + Valid bool + Set bool +} + +func NewNullStrState(val interface{}) (x NullStrState) { + err := x.Scan(val) // yes, we ignore this error, it will just be an invalid value. + _ = err // make any errcheck linters happy + return +} + +// Scan implements the Scanner interface. +func (x *NullStrState) Scan(value interface{}) (err error) { + if value == nil { + x.StrState, x.Valid = StrState(""), false + return + } + + err = x.StrState.Scan(value) + x.Valid = (err == nil) + return +} + +// Value implements the driver Valuer interface. +func (x NullStrState) Value() (driver.Value, error) { + if !x.Valid { + return nil, nil + } + return x.StrState.String(), nil +} + +// MarshalJSON correctly serializes a NullStrState to JSON. +func (n NullStrState) MarshalJSON() ([]byte, error) { + const nullStr = "null" + if n.Valid { + return json.Marshal(n.StrState) + } + return []byte(nullStr), nil +} + +// UnmarshalJSON correctly deserializes a NullStrState from JSON. +func (n *NullStrState) UnmarshalJSON(b []byte) error { + n.Set = true + var x interface{} + err := json.Unmarshal(b, &x) + if err != nil { + return err + } + err = n.Scan(x) + return err +} diff --git a/_example/strings_only_test.go b/_example/strings_only_test.go new file mode 100644 index 00000000..2155b6ca --- /dev/null +++ b/_example/strings_only_test.go @@ -0,0 +1,257 @@ +package example + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestStrState(t *testing.T) { + x := StrState("") + assert.Equal(t, "", x.String()) + + assert.Equal(t, StrState("pending"), StrStatePending) + assert.Equal(t, StrState("running"), StrStateRunning) + assert.Equal(t, &x, StrState("").Ptr()) +} + +func TestStrStateMustParse(t *testing.T) { + x := `avocado` + + assert.PanicsWithError(t, x+" is not a valid StrState, try [pending, running, completed, failed]", func() { MustParseStrState(x) }) + assert.NotPanics(t, func() { MustParseStrState(StrStateFailed.String()) }) +} + +func TestStrStateUnmarshal(t *testing.T) { + type testData struct { + StrStateX StrState `json:"state"` + } + tests := []struct { + name string + input string + output *testData + errorExpected bool + err error + }{ + { + name: "pending", + input: `{"state":"Pending"}`, + output: &testData{StrStateX: StrStatePending}, + errorExpected: false, + err: nil, + }, + { + name: "pendinglower", + input: `{"state":"pending"}`, + output: &testData{StrStateX: StrStatePending}, + errorExpected: false, + err: nil, + }, + { + name: "running", + input: `{"state":"RUNNING"}`, + output: &testData{StrStateX: StrStateRunning}, + errorExpected: false, + err: nil, + }, { + name: "running", + input: `{"state":"running"}`, + output: &testData{StrStateX: StrStateRunning}, + errorExpected: false, + err: nil, + }, + { + name: "completed", + input: `{"state":"Completed"}`, + output: &testData{StrStateX: StrStateCompleted}, + errorExpected: false, + err: nil, + }, + { + name: "completedlower", + input: `{"state":"completed"}`, + output: &testData{StrStateX: StrStateCompleted}, + errorExpected: false, + err: nil, + }, + { + name: "failed", + input: `{"state":"Failed"}`, + output: &testData{StrStateX: StrStateFailed}, + errorExpected: false, + err: nil, + }, + { + name: "failedlower", + input: `{"state":"failed"}`, + output: &testData{StrStateX: StrStateFailed}, + errorExpected: false, + err: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + x := &testData{} + err := json.Unmarshal([]byte(test.input), x) + if !test.errorExpected { + require.NoError(tt, err, "failed unmarshalling the json.") + assert.Equal(tt, test.output.StrStateX, x.StrStateX) + } else { + require.Error(tt, err) + assert.EqualError(tt, err, test.err.Error()) + } + }) + } +} + +func TestStrStateMarshal(t *testing.T) { + type testData struct { + StrStateX StrState `json:"state"` + } + tests := []struct { + name string + input *testData + output string + errorExpected bool + err error + }{ + { + name: "black", + output: `{"state":"pending"}`, + input: &testData{StrStateX: StrStatePending}, + errorExpected: false, + err: nil, + }, + { + name: "white", + output: `{"state":"running"}`, + input: &testData{StrStateX: StrStateRunning}, + errorExpected: false, + err: nil, + }, + { + name: "red", + output: `{"state":"completed"}`, + input: &testData{StrStateX: StrStateCompleted}, + errorExpected: false, + err: nil, + }, + { + name: "green", + output: `{"state":"failed"}`, + input: &testData{StrStateX: StrStateFailed}, + errorExpected: false, + err: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + raw, err := json.Marshal(test.input) + require.NoError(tt, err, "failed marshalling to json") + assert.JSONEq(tt, test.output, string(raw)) + }) + } +} + +func TestStrStateSQLExtras(t *testing.T) { + + _, err := ParseStrState(`NotAState`) + assert.Error(t, err, "Should have had an error parsing a non status") + + var ( + intVal int = 3 + strVal string = "completed" + enumVal StrState = StrStateCompleted + nullInt *int + nullInt64 *int64 + nullUint *uint + nullUint64 *uint64 + nullString *string + nullStrState *StrState + ) + + tests := map[string]struct { + input interface{} + result NullStrState + }{ + "nil": {}, + "val": { + input: StrStatePending, + result: NullStrState{ + StrState: StrStatePending, + Valid: true, + }, + }, + "ptr": { + input: &enumVal, + result: NullStrState{ + StrState: StrStateCompleted, + Valid: true, + }, + }, + "string": { + input: strVal, + result: NullStrState{ + StrState: StrStateCompleted, + Valid: true, + }, + }, + "*string": { + input: &strVal, + result: NullStrState{ + StrState: StrStateCompleted, + Valid: true, + }, + }, + "invalid string": { + input: "random value", + }, + "[]byte": { + input: []byte(StrStateRunning.String()), + result: NullStrState{ + StrState: StrStateRunning, + Valid: true, + }, + }, + "int": { + input: intVal, + }, + "*int": { + input: &intVal, + }, + "nullInt": { + input: nullInt, + }, + "nullInt64": { + input: nullInt64, + }, + "nullUint": { + input: nullUint, + }, + "nullUint64": { + input: nullUint64, + }, + "nullString": { + input: nullString, + }, + "nullImageType": { + input: nullStrState, + }, + "int as []byte": { // must have --sqlnullint flag to get this feature. + input: []byte("3"), + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + status := NewNullStrState(tc.input) + assert.Equal(t, status, tc.result) + + }) + } + +} diff --git a/generator/.snapshots/Test118CustomPrefixExampleFile-og b/generator/.snapshots/Test118CustomPrefixExampleFile-og index 8b0acde4..303980bd 100644 --- a/generator/.snapshots/Test118CustomPrefixExampleFile-og +++ b/generator/.snapshots/Test118CustomPrefixExampleFile-og @@ -1,4 +1,4 @@ -([]string) (len=3639) { +([]string) (len=3841) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -3637,5 +3637,207 @@ (string) (len=16) "\terr = n.Scan(x)", (string) (len=11) "\treturn err", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=56) "\t// Custom_prefix_Random is a StringEnum of type random.", + (string) (len=43) "\tCustom_prefix_Random StringEnum = \"random\"", + (string) (len=56) "\t// Custom_prefix_Values is a StringEnum of type values.", + (string) (len=43) "\tCustom_prefix_Values StringEnum = \"values\"", + (string) (len=52) "\t// Custom_prefix_Here is a StringEnum of type here.", + (string) (len=39) "\tCustom_prefix_Here StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=32) "\t\"random\": Custom_prefix_Random,", + (string) (len=32) "\t\"values\": Custom_prefix_Values,", + (string) (len=30) "\t\"here\": Custom_prefix_Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=39) "func (x StringEnum) Ptr() *StringEnum {", + (string) (len=10) "\treturn &x", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", + (string) "", + (string) (len=28) "type NullStringEnum struct {", + (string) (len=22) "\tStringEnum StringEnum", + (string) (len=16) "\tValid bool", + (string) (len=16) "\tSet bool", + (string) (len=1) "}", + (string) "", + (string) (len=60) "func NewNullStringEnum(val interface{}) (x NullStringEnum) {", + (string) (len=83) "\terr := x.Scan(val) // yes, we ignore this error, it will just be an invalid value.", + (string) (len=54) "\t_ = err // make any errcheck linters happy", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=62) "func (x *NullStringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=47) "\t\tx.StringEnum, x.Valid = StringEnum(\"\"), false", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=31) "\terr = x.StringEnum.Scan(value)", + (string) (len=23) "\tx.Valid = (err == nil)", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=55) "func (x NullStringEnum) Value() (driver.Value, error) {", + (string) (len=14) "\tif !x.Valid {", + (string) (len=17) "\t\treturn nil, nil", + (string) (len=2) "\t}", + (string) (len=46) "\t// driver.Value accepts int64 for int values.", + (string) (len=33) "\treturn string(x.StringEnum), nil", + (string) (len=1) "}", + (string) "", + (string) (len=61) "// MarshalJSON correctly serializes a NullStringEnum to JSON.", + (string) (len=55) "func (n NullStringEnum) MarshalJSON() ([]byte, error) {", + (string) (len=23) "\tconst nullStr = \"null\"", + (string) (len=13) "\tif n.Valid {", + (string) (len=35) "\t\treturn json.Marshal(n.StringEnum)", + (string) (len=2) "\t}", + (string) (len=28) "\treturn []byte(nullStr), nil", + (string) (len=1) "}", + (string) "", + (string) (len=67) "// UnmarshalJSON correctly deserializes a NullStringEnum from JSON.", + (string) (len=56) "func (n *NullStringEnum) UnmarshalJSON(b []byte) error {", + (string) (len=13) "\tn.Set = true", + (string) (len=18) "\tvar x interface{}", + (string) (len=29) "\terr := json.Unmarshal(b, &x)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=16) "\terr = n.Scan(x)", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=31) "type NullStringEnumStr struct {", + (string) (len=15) "\tNullStringEnum", + (string) (len=1) "}", + (string) "", + (string) (len=66) "func NewNullStringEnumStr(val interface{}) (x NullStringEnumStr) {", + (string) (len=76) "\tx.Scan(val) // yes, we ignore this error, it will just be an invalid value.", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=58) "func (x NullStringEnumStr) Value() (driver.Value, error) {", + (string) (len=14) "\tif !x.Valid {", + (string) (len=17) "\t\treturn nil, nil", + (string) (len=2) "\t}", + (string) (len=34) "\treturn x.StringEnum.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=61) "// MarshalJSON correctly serializes a NullStringEnum to JSON.", + (string) (len=58) "func (n NullStringEnumStr) MarshalJSON() ([]byte, error) {", + (string) (len=23) "\tconst nullStr = \"null\"", + (string) (len=13) "\tif n.Valid {", + (string) (len=35) "\t\treturn json.Marshal(n.StringEnum)", + (string) (len=2) "\t}", + (string) (len=28) "\treturn []byte(nullStr), nil", + (string) (len=1) "}", + (string) "", + (string) (len=67) "// UnmarshalJSON correctly deserializes a NullStringEnum from JSON.", + (string) (len=59) "func (n *NullStringEnumStr) UnmarshalJSON(b []byte) error {", + (string) (len=13) "\tn.Set = true", + (string) (len=18) "\tvar x interface{}", + (string) (len=29) "\terr := json.Unmarshal(b, &x)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=16) "\terr = n.Scan(x)", + (string) (len=11) "\treturn err", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/Test118ExampleFile-og b/generator/.snapshots/Test118ExampleFile-og index 274740c9..5cc24931 100644 --- a/generator/.snapshots/Test118ExampleFile-og +++ b/generator/.snapshots/Test118ExampleFile-og @@ -1,4 +1,4 @@ -([]string) (len=2195) { +([]string) (len=2301) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -2193,5 +2193,111 @@ (string) (len=53) "func (x StartNotZero) Value() (driver.Value, error) {", (string) (len=23) "\treturn x.String(), nil", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=52) "\t// StringEnumRandom is a StringEnum of type random.", + (string) (len=39) "\tStringEnumRandom StringEnum = \"random\"", + (string) (len=52) "\t// StringEnumValues is a StringEnum of type values.", + (string) (len=39) "\tStringEnumValues StringEnum = \"values\"", + (string) (len=48) "\t// StringEnumHere is a StringEnum of type here.", + (string) (len=35) "\tStringEnumHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=32) "var _StringEnumNames = []string{", + (string) (len=26) "\tstring(StringEnumRandom),", + (string) (len=26) "\tstring(StringEnumValues),", + (string) (len=24) "\tstring(StringEnumHere),", + (string) (len=1) "}", + (string) "", + (string) (len=74) "// StringEnumNames returns a list of possible string values of StringEnum.", + (string) (len=33) "func StringEnumNames() []string {", + (string) (len=45) "\ttmp := make([]string, len(_StringEnumNames))", + (string) (len=28) "\tcopy(tmp, _StringEnumNames)", + (string) (len=11) "\treturn tmp", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=28) "\t\"random\": StringEnumRandom,", + (string) (len=28) "\t\"values\": StringEnumValues,", + (string) (len=26) "\t\"here\": StringEnumHere,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=121) "\t// Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to.", + (string) (len=58) "\tif x, ok := _StringEnumValue[strings.ToLower(name)]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=120) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum, try [%s]\", name, strings.Join(_StringEnumNames, \", \"))", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/Test118ExampleFileMoreOptions-og b/generator/.snapshots/Test118ExampleFileMoreOptions-og index b334af43..21475684 100644 --- a/generator/.snapshots/Test118ExampleFileMoreOptions-og +++ b/generator/.snapshots/Test118ExampleFileMoreOptions-og @@ -1,4 +1,4 @@ -([]string) (len=2377) { +([]string) (len=2497) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -2375,5 +2375,125 @@ (string) (len=38) "func ParseStartNotZeroExample() bool {", (string) (len=12) "\treturn true", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=52) "\t// StringEnumRandom is a StringEnum of type random.", + (string) (len=39) "\tStringEnumRandom StringEnum = \"random\"", + (string) (len=52) "\t// StringEnumValues is a StringEnum of type values.", + (string) (len=39) "\tStringEnumValues StringEnum = \"values\"", + (string) (len=48) "\t// StringEnumHere is a StringEnum of type here.", + (string) (len=35) "\tStringEnumHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=32) "var _StringEnumNames = []string{", + (string) (len=26) "\tstring(StringEnumRandom),", + (string) (len=26) "\tstring(StringEnumValues),", + (string) (len=24) "\tstring(StringEnumHere),", + (string) (len=1) "}", + (string) "", + (string) (len=74) "// StringEnumNames returns a list of possible string values of StringEnum.", + (string) (len=33) "func StringEnumNames() []string {", + (string) (len=45) "\ttmp := make([]string, len(_StringEnumNames))", + (string) (len=28) "\tcopy(tmp, _StringEnumNames)", + (string) (len=11) "\treturn tmp", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=28) "\t\"random\": StringEnumRandom,", + (string) (len=28) "\t\"values\": StringEnumValues,", + (string) (len=26) "\t\"here\": StringEnumHere,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=121) "\t// Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to.", + (string) (len=58) "\tif x, ok := _StringEnumValue[strings.ToLower(name)]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=120) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum, try [%s]\", name, strings.Join(_StringEnumNames, \", \"))", + (string) (len=1) "}", + (string) "", + (string) (len=85) "// MustParseStringEnum converts a string to a StringEnum, and panics if is not valid.", + (string) (len=50) "func MustParseStringEnum(name string) StringEnum {", + (string) (len=34) "\tval, err := ParseStringEnum(name)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\tpanic(err)", + (string) (len=2) "\t}", + (string) (len=11) "\treturn val", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=22) "// Additional template", + (string) (len=36) "func ParseStringEnumExample() bool {", + (string) (len=12) "\treturn true", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/Test118NoPrefixExampleFile-og b/generator/.snapshots/Test118NoPrefixExampleFile-og index 5c845855..8207acdf 100644 --- a/generator/.snapshots/Test118NoPrefixExampleFile-og +++ b/generator/.snapshots/Test118NoPrefixExampleFile-og @@ -1,4 +1,4 @@ -([]string) (len=1203) { +([]string) (len=1269) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -1201,5 +1201,71 @@ (string) (len=38) "func (x *StartNotZero) Type() string {", (string) (len=22) "\treturn \"StartNotZero\"", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=42) "\t// Random is a StringEnum of type random.", + (string) (len=29) "\tRandom StringEnum = \"random\"", + (string) (len=42) "\t// Values is a StringEnum of type values.", + (string) (len=29) "\tValues StringEnum = \"values\"", + (string) (len=38) "\t// Here is a StringEnum of type here.", + (string) (len=25) "\tHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=18) "\t\"random\": Random,", + (string) (len=18) "\t\"values\": Values,", + (string) (len=16) "\t\"here\": Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/Test118NoPrefixExampleFileWithSnakeToCamel-og b/generator/.snapshots/Test118NoPrefixExampleFileWithSnakeToCamel-og index f6e55067..9eeb1ec1 100644 --- a/generator/.snapshots/Test118NoPrefixExampleFileWithSnakeToCamel-og +++ b/generator/.snapshots/Test118NoPrefixExampleFileWithSnakeToCamel-og @@ -1,4 +1,4 @@ -([]string) (len=1203) { +([]string) (len=1269) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -1201,5 +1201,71 @@ (string) (len=38) "func (x *StartNotZero) Type() string {", (string) (len=22) "\treturn \"StartNotZero\"", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=42) "\t// Random is a StringEnum of type random.", + (string) (len=29) "\tRandom StringEnum = \"random\"", + (string) (len=42) "\t// Values is a StringEnum of type values.", + (string) (len=29) "\tValues StringEnum = \"values\"", + (string) (len=38) "\t// Here is a StringEnum of type here.", + (string) (len=25) "\tHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=18) "\t\"random\": Random,", + (string) (len=18) "\t\"values\": Values,", + (string) (len=16) "\t\"here\": Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/TestCustomPrefixExampleFile b/generator/.snapshots/TestCustomPrefixExampleFile index 8b0acde4..303980bd 100644 --- a/generator/.snapshots/TestCustomPrefixExampleFile +++ b/generator/.snapshots/TestCustomPrefixExampleFile @@ -1,4 +1,4 @@ -([]string) (len=3639) { +([]string) (len=3841) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -3637,5 +3637,207 @@ (string) (len=16) "\terr = n.Scan(x)", (string) (len=11) "\treturn err", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=56) "\t// Custom_prefix_Random is a StringEnum of type random.", + (string) (len=43) "\tCustom_prefix_Random StringEnum = \"random\"", + (string) (len=56) "\t// Custom_prefix_Values is a StringEnum of type values.", + (string) (len=43) "\tCustom_prefix_Values StringEnum = \"values\"", + (string) (len=52) "\t// Custom_prefix_Here is a StringEnum of type here.", + (string) (len=39) "\tCustom_prefix_Here StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=32) "\t\"random\": Custom_prefix_Random,", + (string) (len=32) "\t\"values\": Custom_prefix_Values,", + (string) (len=30) "\t\"here\": Custom_prefix_Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=39) "func (x StringEnum) Ptr() *StringEnum {", + (string) (len=10) "\treturn &x", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", + (string) "", + (string) (len=28) "type NullStringEnum struct {", + (string) (len=22) "\tStringEnum StringEnum", + (string) (len=16) "\tValid bool", + (string) (len=16) "\tSet bool", + (string) (len=1) "}", + (string) "", + (string) (len=60) "func NewNullStringEnum(val interface{}) (x NullStringEnum) {", + (string) (len=83) "\terr := x.Scan(val) // yes, we ignore this error, it will just be an invalid value.", + (string) (len=54) "\t_ = err // make any errcheck linters happy", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=62) "func (x *NullStringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=47) "\t\tx.StringEnum, x.Valid = StringEnum(\"\"), false", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=31) "\terr = x.StringEnum.Scan(value)", + (string) (len=23) "\tx.Valid = (err == nil)", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=55) "func (x NullStringEnum) Value() (driver.Value, error) {", + (string) (len=14) "\tif !x.Valid {", + (string) (len=17) "\t\treturn nil, nil", + (string) (len=2) "\t}", + (string) (len=46) "\t// driver.Value accepts int64 for int values.", + (string) (len=33) "\treturn string(x.StringEnum), nil", + (string) (len=1) "}", + (string) "", + (string) (len=61) "// MarshalJSON correctly serializes a NullStringEnum to JSON.", + (string) (len=55) "func (n NullStringEnum) MarshalJSON() ([]byte, error) {", + (string) (len=23) "\tconst nullStr = \"null\"", + (string) (len=13) "\tif n.Valid {", + (string) (len=35) "\t\treturn json.Marshal(n.StringEnum)", + (string) (len=2) "\t}", + (string) (len=28) "\treturn []byte(nullStr), nil", + (string) (len=1) "}", + (string) "", + (string) (len=67) "// UnmarshalJSON correctly deserializes a NullStringEnum from JSON.", + (string) (len=56) "func (n *NullStringEnum) UnmarshalJSON(b []byte) error {", + (string) (len=13) "\tn.Set = true", + (string) (len=18) "\tvar x interface{}", + (string) (len=29) "\terr := json.Unmarshal(b, &x)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=16) "\terr = n.Scan(x)", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=31) "type NullStringEnumStr struct {", + (string) (len=15) "\tNullStringEnum", + (string) (len=1) "}", + (string) "", + (string) (len=66) "func NewNullStringEnumStr(val interface{}) (x NullStringEnumStr) {", + (string) (len=76) "\tx.Scan(val) // yes, we ignore this error, it will just be an invalid value.", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=58) "func (x NullStringEnumStr) Value() (driver.Value, error) {", + (string) (len=14) "\tif !x.Valid {", + (string) (len=17) "\t\treturn nil, nil", + (string) (len=2) "\t}", + (string) (len=34) "\treturn x.StringEnum.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=61) "// MarshalJSON correctly serializes a NullStringEnum to JSON.", + (string) (len=58) "func (n NullStringEnumStr) MarshalJSON() ([]byte, error) {", + (string) (len=23) "\tconst nullStr = \"null\"", + (string) (len=13) "\tif n.Valid {", + (string) (len=35) "\t\treturn json.Marshal(n.StringEnum)", + (string) (len=2) "\t}", + (string) (len=28) "\treturn []byte(nullStr), nil", + (string) (len=1) "}", + (string) "", + (string) (len=67) "// UnmarshalJSON correctly deserializes a NullStringEnum from JSON.", + (string) (len=59) "func (n *NullStringEnumStr) UnmarshalJSON(b []byte) error {", + (string) (len=13) "\tn.Set = true", + (string) (len=18) "\tvar x interface{}", + (string) (len=29) "\terr := json.Unmarshal(b, &x)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=16) "\terr = n.Scan(x)", + (string) (len=11) "\treturn err", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/TestExampleFile b/generator/.snapshots/TestExampleFile index 274740c9..5cc24931 100644 --- a/generator/.snapshots/TestExampleFile +++ b/generator/.snapshots/TestExampleFile @@ -1,4 +1,4 @@ -([]string) (len=2195) { +([]string) (len=2301) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -2193,5 +2193,111 @@ (string) (len=53) "func (x StartNotZero) Value() (driver.Value, error) {", (string) (len=23) "\treturn x.String(), nil", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=52) "\t// StringEnumRandom is a StringEnum of type random.", + (string) (len=39) "\tStringEnumRandom StringEnum = \"random\"", + (string) (len=52) "\t// StringEnumValues is a StringEnum of type values.", + (string) (len=39) "\tStringEnumValues StringEnum = \"values\"", + (string) (len=48) "\t// StringEnumHere is a StringEnum of type here.", + (string) (len=35) "\tStringEnumHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=32) "var _StringEnumNames = []string{", + (string) (len=26) "\tstring(StringEnumRandom),", + (string) (len=26) "\tstring(StringEnumValues),", + (string) (len=24) "\tstring(StringEnumHere),", + (string) (len=1) "}", + (string) "", + (string) (len=74) "// StringEnumNames returns a list of possible string values of StringEnum.", + (string) (len=33) "func StringEnumNames() []string {", + (string) (len=45) "\ttmp := make([]string, len(_StringEnumNames))", + (string) (len=28) "\tcopy(tmp, _StringEnumNames)", + (string) (len=11) "\treturn tmp", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=28) "\t\"random\": StringEnumRandom,", + (string) (len=28) "\t\"values\": StringEnumValues,", + (string) (len=26) "\t\"here\": StringEnumHere,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=121) "\t// Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to.", + (string) (len=58) "\tif x, ok := _StringEnumValue[strings.ToLower(name)]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=120) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum, try [%s]\", name, strings.Join(_StringEnumNames, \", \"))", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/TestExampleFileMoreOptions b/generator/.snapshots/TestExampleFileMoreOptions index b334af43..21475684 100644 --- a/generator/.snapshots/TestExampleFileMoreOptions +++ b/generator/.snapshots/TestExampleFileMoreOptions @@ -1,4 +1,4 @@ -([]string) (len=2377) { +([]string) (len=2497) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -2375,5 +2375,125 @@ (string) (len=38) "func ParseStartNotZeroExample() bool {", (string) (len=12) "\treturn true", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=52) "\t// StringEnumRandom is a StringEnum of type random.", + (string) (len=39) "\tStringEnumRandom StringEnum = \"random\"", + (string) (len=52) "\t// StringEnumValues is a StringEnum of type values.", + (string) (len=39) "\tStringEnumValues StringEnum = \"values\"", + (string) (len=48) "\t// StringEnumHere is a StringEnum of type here.", + (string) (len=35) "\tStringEnumHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=32) "var _StringEnumNames = []string{", + (string) (len=26) "\tstring(StringEnumRandom),", + (string) (len=26) "\tstring(StringEnumValues),", + (string) (len=24) "\tstring(StringEnumHere),", + (string) (len=1) "}", + (string) "", + (string) (len=74) "// StringEnumNames returns a list of possible string values of StringEnum.", + (string) (len=33) "func StringEnumNames() []string {", + (string) (len=45) "\ttmp := make([]string, len(_StringEnumNames))", + (string) (len=28) "\tcopy(tmp, _StringEnumNames)", + (string) (len=11) "\treturn tmp", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=28) "\t\"random\": StringEnumRandom,", + (string) (len=28) "\t\"values\": StringEnumValues,", + (string) (len=26) "\t\"here\": StringEnumHere,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=121) "\t// Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to.", + (string) (len=58) "\tif x, ok := _StringEnumValue[strings.ToLower(name)]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=120) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum, try [%s]\", name, strings.Join(_StringEnumNames, \", \"))", + (string) (len=1) "}", + (string) "", + (string) (len=85) "// MustParseStringEnum converts a string to a StringEnum, and panics if is not valid.", + (string) (len=50) "func MustParseStringEnum(name string) StringEnum {", + (string) (len=34) "\tval, err := ParseStringEnum(name)", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\tpanic(err)", + (string) (len=2) "\t}", + (string) (len=11) "\treturn val", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=97) "var _StringEnumErrNilPtr = errors.New(\"value pointer is nil\") // one per type for package clashes", + (string) "", + (string) (len=41) "// Scan implements the Scanner interface.", + (string) (len=58) "func (x *StringEnum) Scan(value interface{}) (err error) {", + (string) (len=18) "\tif value == nil {", + (string) (len=21) "\t\t*x = StringEnum(\"\")", + (string) (len=8) "\t\treturn", + (string) (len=2) "\t}", + (string) "", + (string) (len=37) "\t// A wider range of scannable types.", + (string) (len=61) "\t// driver.Value values at the top of the list for expediency", + (string) (len=27) "\tswitch v := value.(type) {", + (string) (len=13) "\tcase string:", + (string) (len=30) "\t\t*x, err = ParseStringEnum(v)", + (string) (len=13) "\tcase []byte:", + (string) (len=38) "\t\t*x, err = ParseStringEnum(string(v))", + (string) (len=17) "\tcase StringEnum:", + (string) (len=8) "\t\t*x = v", + (string) (len=18) "\tcase *StringEnum:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=9) "\t\t*x = *v", + (string) (len=14) "\tcase *string:", + (string) (len=15) "\t\tif v == nil {", + (string) (len=30) "\t\t\treturn _StringEnumErrNilPtr", + (string) (len=3) "\t\t}", + (string) (len=31) "\t\t*x, err = ParseStringEnum(*v)", + (string) (len=9) "\tdefault:", + (string) (len=50) "\t\treturn errors.New(\"invalid type for StringEnum\")", + (string) (len=2) "\t}", + (string) "", + (string) (len=7) "\treturn", + (string) (len=1) "}", + (string) "", + (string) (len=48) "// Value implements the driver Valuer interface.", + (string) (len=51) "func (x StringEnum) Value() (driver.Value, error) {", + (string) (len=23) "\treturn x.String(), nil", + (string) (len=1) "}", + (string) "", + (string) (len=22) "// Additional template", + (string) (len=36) "func ParseStringEnumExample() bool {", + (string) (len=12) "\treturn true", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/TestNoPrefixExampleFile b/generator/.snapshots/TestNoPrefixExampleFile index 5c845855..8207acdf 100644 --- a/generator/.snapshots/TestNoPrefixExampleFile +++ b/generator/.snapshots/TestNoPrefixExampleFile @@ -1,4 +1,4 @@ -([]string) (len=1203) { +([]string) (len=1269) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -1201,5 +1201,71 @@ (string) (len=38) "func (x *StartNotZero) Type() string {", (string) (len=22) "\treturn \"StartNotZero\"", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=42) "\t// Random is a StringEnum of type random.", + (string) (len=29) "\tRandom StringEnum = \"random\"", + (string) (len=42) "\t// Values is a StringEnum of type values.", + (string) (len=29) "\tValues StringEnum = \"values\"", + (string) (len=38) "\t// Here is a StringEnum of type here.", + (string) (len=25) "\tHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=18) "\t\"random\": Random,", + (string) (len=18) "\t\"values\": Values,", + (string) (len=16) "\t\"here\": Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", (string) "" } diff --git a/generator/.snapshots/TestNoPrefixExampleFileWithSnakeToCamel b/generator/.snapshots/TestNoPrefixExampleFileWithSnakeToCamel index f6e55067..9eeb1ec1 100644 --- a/generator/.snapshots/TestNoPrefixExampleFileWithSnakeToCamel +++ b/generator/.snapshots/TestNoPrefixExampleFileWithSnakeToCamel @@ -1,4 +1,4 @@ -([]string) (len=1203) { +([]string) (len=1269) { (string) (len=41) "// Code generated by go-enum DO NOT EDIT.", (string) (len=13) "// Version: -", (string) (len=14) "// Revision: -", @@ -1201,5 +1201,71 @@ (string) (len=38) "func (x *StartNotZero) Type() string {", (string) (len=22) "\treturn \"StartNotZero\"", (string) (len=1) "}", + (string) "", + (string) (len=7) "const (", + (string) (len=42) "\t// Random is a StringEnum of type random.", + (string) (len=29) "\tRandom StringEnum = \"random\"", + (string) (len=42) "\t// Values is a StringEnum of type values.", + (string) (len=29) "\tValues StringEnum = \"values\"", + (string) (len=38) "\t// Here is a StringEnum of type here.", + (string) (len=25) "\tHere StringEnum = \"here\"", + (string) (len=1) ")", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=37) "func (x StringEnum) String() string {", + (string) (len=17) "\treturn string(x)", + (string) (len=1) "}", + (string) "", + (string) (len=44) "// String implements the Stringer interface.", + (string) (len=36) "func (x StringEnum) IsValid() bool {", + (string) (len=37) "\t_, err := ParseStringEnum(string(x))", + (string) (len=18) "\treturn err == nil", + (string) (len=1) "}", + (string) "", + (string) (len=45) "var _StringEnumValue = map[string]StringEnum{", + (string) (len=18) "\t\"random\": Random,", + (string) (len=18) "\t\"values\": Values,", + (string) (len=16) "\t\"here\": Here,", + (string) (len=1) "}", + (string) "", + (string) (len=64) "// ParseStringEnum attempts to convert a string to a StringEnum.", + (string) (len=55) "func ParseStringEnum(name string) (StringEnum, error) {", + (string) (len=41) "\tif x, ok := _StringEnumValue[name]; ok {", + (string) (len=15) "\t\treturn x, nil", + (string) (len=2) "\t}", + (string) (len=72) "\treturn StringEnum(\"\"), fmt.Errorf(\"%s is not a valid StringEnum\", name)", + (string) (len=1) "}", + (string) "", + (string) (len=53) "// MarshalText implements the text marshaller method.", + (string) (len=51) "func (x StringEnum) MarshalText() ([]byte, error) {", + (string) (len=30) "\treturn []byte(string(x)), nil", + (string) (len=1) "}", + (string) "", + (string) (len=57) "// UnmarshalText implements the text unmarshaller method.", + (string) (len=55) "func (x *StringEnum) UnmarshalText(text []byte) error {", + (string) (len=42) "\ttmp, err := ParseStringEnum(string(text))", + (string) (len=16) "\tif err != nil {", + (string) (len=12) "\t\treturn err", + (string) (len=2) "\t}", + (string) (len=9) "\t*x = tmp", + (string) (len=11) "\treturn nil", + (string) (len=1) "}", + (string) "", + (string) (len=55) "// Set implements the Golang flag.Value interface func.", + (string) (len=44) "func (x *StringEnum) Set(val string) error {", + (string) (len=31) "\tv, err := ParseStringEnum(val)", + (string) (len=7) "\t*x = v", + (string) (len=11) "\treturn err", + (string) (len=1) "}", + (string) "", + (string) (len=56) "// Get implements the Golang flag.Getter interface func.", + (string) (len=40) "func (x *StringEnum) Get() interface{} {", + (string) (len=10) "\treturn *x", + (string) (len=1) "}", + (string) "", + (string) (len=62) "// Type implements the github.com/spf13/pFlag Value interface.", + (string) (len=36) "func (x *StringEnum) Type() string {", + (string) (len=20) "\treturn \"StringEnum\"", + (string) (len=1) "}", (string) "" } diff --git a/generator/assets/assets.go b/generator/assets/assets.go index c752feea..35788873 100644 --- a/generator/assets/assets.go +++ b/generator/assets/assets.go @@ -1,6 +1,7 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: // enum.tmpl (8.705kB) +// enum_string.tmpl (6.809kB) package assets @@ -89,6 +90,26 @@ func enumTmpl() (*asset, error) { return a, nil } +var _enum_stringTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x58\xdf\x8f\xe3\xb6\x11\x7e\xb6\xfe\x8a\x89\x90\xa4\xd2\x42\x91\x5b\xb4\xe8\xc3\x15\x7e\x08\x82\xf4\x90\xa0\xdd\x1e\xba\xd7\xbc\x1c\x0e\x0b\xae\x34\x5a\x33\x4b\x91\x0a\x49\xdb\x72\x05\xfd\xef\xc5\x90\x94\x2c\xcb\x5a\xef\xa5\xd9\xa6\x28\x7a\x0f\x07\x53\x24\x87\xdf\x7c\xfc\xe6\x07\xb7\xeb\xbe\x82\x12\x2b\x2e\x11\x62\x94\xbb\xfa\xde\x58\xcd\xe5\x63\xdc\xf7\x51\xa1\xa4\xb1\x90\x44\xb4\xe4\x73\x9a\xbb\x65\x35\xc2\x9b\x0d\xe4\x34\xc8\xdd\xe8\xab\xbe\x3f\xcd\xbf\x3f\x36\x93\x79\x37\x1a\xe7\xf7\x4c\x1b\x9a\x2b\x79\x61\x21\x16\xcc\x58\x55\x55\x06\x6d\x0c\xf1\x6f\xe3\xb0\x0c\x34\x93\x8f\x08\x9f\xeb\xef\x64\x89\x6d\x46\x9b\xc4\x6e\x62\xf1\x07\x1a\x1a\xe8\xfb\x68\xd5\x75\xc0\x2b\xc0\x9f\xc2\x1a\x0f\x26\xbe\x8f\xfb\x7e\xbd\x86\xbb\x27\xde\x34\x58\x82\x9f\xea\x3a\x14\x06\xdd\x44\xd7\x85\xe5\xef\x34\x56\xbc\xc5\x92\xb6\xf5\x3d\x70\x03\x8c\x26\x07\x27\xfb\x1e\x54\x05\x96\x1c\x18\xb7\xfc\x9d\x1d\xfc\x14\x19\x94\xa5\x07\xf1\x15\xa1\x08\x0b\xbe\x51\x75\x8d\xd2\xd2\xc4\xf4\xa8\xc9\x67\x5a\xef\xb7\x02\xc0\xb3\x60\xce\x71\x6c\x20\xbe\x84\x10\x47\x27\x53\x69\x14\x79\x32\x72\xc9\x6a\xc7\xce\x9e\x69\xb8\xef\xba\xd3\x2d\xf5\xfd\xad\x9b\xda\x40\xd7\x49\x56\xf3\xea\xe8\x09\xed\xfb\x28\x72\x50\x2f\x97\x6a\xb4\x3b\x2d\x89\x16\xc1\x8d\x25\x36\x1a\x65\x0c\x7f\x10\x08\x5e\x20\x9e\x5c\x43\x33\xe7\xfb\xf3\xa8\xda\xc9\x62\xc9\x68\x92\xc2\x87\x8f\x61\x77\x17\xad\x6c\xdd\xd0\xd5\xd6\xec\x09\x93\xe1\x7b\x06\x02\x65\xb2\x04\x3e\x4d\xa3\x55\xa1\x9a\x63\x62\xeb\x26\x5b\x74\x2f\x8d\x56\x1e\x35\xd8\xba\x89\x9c\x9e\x50\x96\x4e\x5a\xe4\xe5\x9d\x3f\x98\xd7\x8d\x40\xba\x10\x03\x76\x8b\xe1\x2b\x6a\xe0\xd2\xa2\xae\x58\x81\x01\x7f\xd2\xce\x5c\x48\xc3\xda\x24\x85\x93\x0f\xe1\x40\xff\x21\x69\xd3\xe8\xb5\xce\xfa\xce\xfc\xc0\x04\x2f\x93\x14\x1e\x94\x12\x74\xd4\x7d\x06\xa8\x35\x31\xf6\x8e\x69\x83\xe7\x1b\x92\x11\xc1\x89\x05\x5a\xbd\xd9\x80\xe4\x82\x50\x2d\x88\xc2\x85\x93\x13\x05\xec\x64\xcd\x9a\x51\x17\x90\x0b\x75\x40\x5d\x30\x83\x10\xd8\x5b\x38\x13\x98\xb5\x58\x37\xe4\x9c\x82\x42\xc9\x3d\x6a\x0b\x6c\x20\xc7\x2a\x17\x52\x0b\xca\x58\x82\x4f\xd2\x0d\x3b\x53\x48\xce\x27\x9d\xdf\x4a\xa7\x44\x02\xaf\xa0\xcd\x40\x3d\x11\x0d\x4b\xde\x7c\x20\x43\x1f\xff\x44\x2b\xba\x68\x35\x30\xd1\x66\x8e\x85\x55\xdf\x75\x2e\x4e\xd4\xe0\x19\x05\xea\x37\xf4\x9b\x4b\x83\xd2\x70\xcb\xf7\x08\x0d\xe1\xcb\xa0\x24\x07\x0c\x36\x4c\x33\x8b\x20\x94\x7a\xda\x35\xe4\x55\xa3\x71\x8f\xd2\xc2\x4e\x4a\x2c\xd0\x18\xa6\x8f\x50\x28\x1f\x23\x03\x6d\x44\xc0\xc8\x04\xaf\xe0\x80\x50\x2a\xf9\x1b\x0b\x12\xb1\x04\xab\xf2\x4f\xf0\xc4\xef\x36\xf9\x7b\xf5\x17\xb2\xea\x28\x4a\xaf\xb9\x36\x24\x84\x55\xf0\xd2\xc5\x31\xa9\x7f\x58\x3b\xe3\x3c\x8e\xd3\x0c\xaa\xda\xe6\xdf\x12\xbd\x55\x12\x7f\x61\x28\x11\x4a\x45\xb7\xb8\x27\xf5\xc1\xfc\x22\xac\x3e\xc2\x87\x2f\xcc\xc7\x38\x03\x32\x9f\xc1\x00\xf2\x7b\xc5\x97\xc3\x36\x83\x38\x83\x98\x54\xe9\x00\x0a\x83\xaf\x0a\x29\x00\x49\xa7\xb9\xb5\x1f\x13\x62\xbd\x33\xd6\xdd\x26\xdd\xf5\x7a\x0d\x7f\xdd\x19\xbb\x24\xe4\x20\x5e\x73\x55\xbd\x19\x30\x59\x42\xc3\x24\x2f\x0c\x59\x0f\xb8\x1c\xaa\xa0\xec\x67\xec\x9f\xab\x7b\x76\x76\x17\xad\xf6\x4c\x5c\x8d\xed\xe0\x21\xd5\x3b\xad\xe1\x33\x17\xd2\x4e\x03\x0e\x4c\x82\x5a\xa7\xd1\xea\xc4\xe9\x9e\x09\x97\xfd\x3c\x1b\x03\x17\x8d\xd5\xc4\xc2\x73\xf9\xe6\x9d\xd5\x49\x0a\x37\x97\xe0\x82\xd1\x2f\xdb\x05\x9b\x35\xd3\x66\xcb\xc4\xc0\xae\x1f\xbd\xc7\xd6\xce\x33\x9f\xa5\x6f\x61\xb5\x40\x0d\x35\xda\xad\x2a\x9f\xcf\x7e\x13\x53\x49\x0a\xc9\x87\x8f\x0f\x47\x8b\xd3\x3c\x10\x50\xf9\x89\x49\xf2\xcb\x86\x74\xb7\x5e\xc3\x3f\x64\xfd\x02\xa2\x9d\xbc\x82\xe9\x66\x0e\xea\xcc\x5e\xe2\x0c\xf8\xf3\x53\x0f\x2c\xd4\xb4\x4f\x49\xd3\xb4\x39\x5d\xbc\xd2\x53\xee\x76\x57\x7a\xd3\xc2\xc6\x95\xb3\x61\xc2\xbb\x37\xbb\x08\xa5\x21\x37\x3f\x09\xf7\x9f\xdc\x09\xc1\xa5\x1d\x7f\x1b\xab\xfb\x7e\x29\xfb\x7f\xab\xf5\x2d\x17\xef\xac\x86\x8d\xc7\x6f\xf2\x5b\x3c\x24\xb1\xef\xb9\x1a\xe5\x8a\x94\x53\x39\x17\x71\x0a\xeb\x35\x28\x89\xd0\xa0\xf6\x7d\x51\xa5\x34\x34\xac\x78\x62\x8f\x08\x85\x60\x66\x8b\xc6\x97\xbe\x82\xc9\x8b\xc2\x57\x30\x29\x97\xeb\xde\x05\xcb\xb4\x36\xf1\x18\xc6\xe5\x5d\x9f\x02\xc9\xfc\xbc\x10\xf8\x45\x9b\x13\x77\x8e\xac\xcb\x8c\x32\xb2\x4a\x8c\xba\x94\xff\x35\x1c\x78\x89\x3a\xb4\x9b\xaa\x02\x43\x00\x19\x35\x37\xe4\x9b\xc9\xdd\xaa\x52\xf3\x3d\x6a\xdf\x74\x0e\xdd\x0e\xb3\x5e\x3d\xaa\x71\x0d\xe2\x16\x7d\x7b\x44\x64\x60\xdb\x60\xc9\x51\x16\xc7\x68\x65\x0e\xdc\x16\x5b\xd8\x93\x0c\x7c\xeb\x96\x90\x61\x87\xdc\xd5\x1e\xaf\x83\x37\x0e\xb4\x17\xcc\xb2\x5e\xf6\x69\xd8\xe0\x95\xf6\xf2\x86\x20\xb0\x7d\x3a\x6c\x3c\x9f\x7f\x33\xd0\xb4\x0f\xd3\x37\x97\xf3\x44\x6d\xa0\x95\x58\x1d\x94\xf7\x9c\x7c\xa2\x15\x09\xd5\x5b\xbd\x19\xcd\x9e\x1c\xfc\x77\xcd\x5d\xf3\xf2\x86\x78\x29\xb1\x62\x3b\x61\xdf\x9c\x45\xcd\x28\x63\x2e\x7d\xbd\x18\xc5\x3a\x2b\x1c\x3e\x65\x8e\x71\x15\x3d\x1b\x4c\xc6\x27\xce\xf5\x1a\xbc\x12\x66\xda\xf6\x2a\xf1\x73\x9f\xd4\xd9\xb9\x95\x94\xd5\xa6\xfa\x5a\xc8\x6d\x6d\x3e\xf4\x9b\xd9\x18\xf5\xbe\x80\xfe\x37\xd0\x8c\x29\x36\xbb\x4c\x41\xe1\xc7\x50\x15\x2a\xc1\x1e\x03\xc6\x3b\xbc\x48\xbc\x6f\x95\x60\xf2\x11\x68\x51\x08\xad\x11\x25\x10\xc8\x6b\xa9\x01\x2d\x65\x86\xb1\x92\x8e\x59\x77\x7f\x35\xe7\xee\x99\x48\xa3\x51\xf5\x93\x04\xeb\xcb\xc4\xdb\xeb\x18\xdf\xa2\xb5\x53\x2a\x5f\x02\xf9\x16\xa9\x64\x4d\x52\xd7\x84\xc4\x9b\x36\x9c\xe9\x9e\xc6\xb3\x43\x1f\xb9\xdd\xee\x1e\xf2\x42\xd5\x6b\xd3\x54\xbf\xfb\xfd\xba\xf9\x33\x11\x39\xe3\xe8\xca\xc9\x64\x74\xe9\x71\x12\xcf\x94\xff\x6c\xfd\x58\x28\x1d\x74\x8f\x2e\x82\x6e\x77\x42\xcc\x9a\x03\x63\xf5\xae\xb0\x1d\xb5\x5e\xd3\xef\xb3\x61\xb4\x72\x0f\x19\x58\xd1\x3f\x7a\xcb\x74\xdd\xfa\x06\xbe\x2e\x4b\x30\xaa\x26\xc7\x2a\x05\xcc\x3d\x21\x0e\x5b\xb4\x5b\x2a\x2f\x5b\x6e\x42\x72\x3f\x30\x03\x06\x2d\x94\x3b\xe7\xd3\xa9\x5e\xd3\x48\x69\xd7\x80\xdd\xac\xfb\xd0\xd7\x4f\xda\x91\xd5\x1d\xda\xd5\x6a\x72\xa6\x7b\x0a\xfa\xe6\xd0\x11\x78\x8b\x87\x4b\x97\x9c\xba\xce\xab\x4e\xbb\xe0\xb9\x8b\x8b\x20\xb8\x36\x1f\x0a\x96\x2b\x91\x47\xea\x78\x0f\x08\xfc\x51\x2a\x8d\xde\x15\x27\xd3\x0c\xb8\x85\x03\x17\x02\x7e\xdc\x19\x0b\x0f\x08\x54\x26\x43\x8e\xf2\x25\x22\x5a\xdd\xfb\x52\x4c\x86\xe8\x55\x0c\x4c\x1e\x69\x5c\x6c\xb1\x78\x02\xe1\x80\x19\xd8\xb2\xa6\x39\x0e\x97\x3b\xbc\x37\x7f\x66\xd1\x5d\xf2\xe9\x17\x14\xde\x36\x9f\xb7\xca\x6d\xee\x6f\x7d\xa9\x1e\x67\x50\x31\x61\x70\x56\x96\x7d\xb2\x9f\x5b\xca\x4f\xa8\xd2\x68\x75\xb2\x9a\x9c\x1e\xb7\xe9\x94\x8b\x90\x82\x26\x62\xfe\x25\xc9\x72\x89\xa6\x17\x13\x26\xaf\xe0\xb3\x00\x74\xd2\xd0\x49\x2e\x86\x97\xda\x65\x73\xc1\x8a\x02\xe9\x1d\xcd\xa5\xfd\xe3\x1f\x5c\xb1\x22\xe4\xbe\xe5\xc8\x2f\x52\xf0\x8c\xa2\x57\x2d\x0f\xff\x29\x8f\xc7\x9a\x36\xbf\xde\x85\x12\xe7\x03\xf5\xea\x1b\xe3\xfb\xbb\xbf\xdd\x42\xa1\xb4\xc6\xc2\x8a\x23\x18\xd4\x9c\x09\xfe\x4f\x6a\xd0\x96\x32\x95\x55\x40\x3b\x06\x37\xe5\xa2\x9b\x13\xd3\xcb\x6f\x0e\xff\xe7\x50\xd2\xd5\x9d\x6b\x9a\x63\xfa\x19\x3b\xf7\x65\x10\xe6\xc4\xfd\x1f\x8d\x92\x79\xb0\x99\xc8\xf9\x9d\x4d\x49\x09\x8f\x98\x60\x78\xf9\x09\x33\x73\xb8\xc4\x97\x5c\xae\xb4\xaa\x67\x4e\x2f\x46\xfd\xd9\x09\xc9\xc3\xe5\x8b\x46\xe6\x54\xc4\x37\x60\xf5\x0e\xe9\xa9\xaa\xa1\x9d\xe6\x87\x31\x11\x3a\x7f\x47\x6b\xc9\x43\x06\x5f\xb6\xf3\x17\xce\xc2\x03\xc7\x87\xbd\xf4\x71\xde\xa6\xb3\xfa\x7c\x2e\x87\x73\x65\xd0\x6b\xfc\xe7\x57\x2d\xba\x3a\x5f\xb8\xc8\xb9\xcb\xf9\xeb\x05\xe2\xce\xea\x4f\xac\x11\x74\x93\x74\xc2\xab\xd6\x87\xb3\x9c\xff\x5a\x01\xee\x90\xfe\xca\x31\xfe\x2b\x06\xb6\x73\xef\xff\x31\xb6\x9d\xe3\xff\x2b\xe1\x7d\x16\xdd\xbe\x37\xfd\x57\x00\x00\x00\xff\xff\x3c\xf0\x77\x54\x99\x1a\x00\x00") + +func enum_stringTmplBytes() ([]byte, error) { + return bindataRead( + _enum_stringTmpl, + "enum_string.tmpl", + ) +} + +func enum_stringTmpl() (*asset, error) { + bytes, err := enum_stringTmplBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "enum_string.tmpl", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfe, 0xa9, 0x87, 0x91, 0xfe, 0x92, 0x4a, 0x77, 0xd1, 0x36, 0x45, 0x3b, 0x9a, 0x5b, 0x45, 0x6f, 0x66, 0xf9, 0x6e, 0x76, 0xbd, 0xdd, 0xbd, 0x93, 0xbc, 0xc8, 0x1c, 0x97, 0x7, 0x89, 0xb3, 0xd1}} + return a, nil +} + // Asset loads and returns the asset for the given name. // It returns an error if the asset could not be found or // could not be loaded. @@ -180,7 +201,8 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "enum.tmpl": enumTmpl, + "enum.tmpl": enumTmpl, + "enum_string.tmpl": enum_stringTmpl, } // AssetDebug is true if the assets were built with the debug flag enabled. @@ -228,6 +250,7 @@ type bintree struct { var _bintree = &bintree{nil, map[string]*bintree{ "enum.tmpl": {enumTmpl, map[string]*bintree{}}, + "enum_string.tmpl": {enum_stringTmpl, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/generator/embedded.go b/generator/embedded.go index 47d6bbfd..3f659d9e 100644 --- a/generator/embedded.go +++ b/generator/embedded.go @@ -1,4 +1,4 @@ -//go:generate ../bin/go-bindata -nometadata -o assets/assets.go -pkg=assets enum.tmpl +//go:generate ../bin/go-bindata -nometadata -o assets/assets.go -pkg=assets enum.tmpl enum_string.tmpl //go:build !go1.16 // +build !go1.16 diff --git a/generator/embedded_1.16.go b/generator/embedded_1.16.go index 83b12a94..ea64de94 100644 --- a/generator/embedded_1.16.go +++ b/generator/embedded_1.16.go @@ -8,7 +8,7 @@ import ( "text/template" ) -//go:embed enum.tmpl +//go:embed enum.tmpl enum_string.tmpl var content embed.FS func (g *Generator) addEmbeddedTemplates() { diff --git a/generator/enum_string.tmpl b/generator/enum_string.tmpl new file mode 100644 index 00000000..b53218c3 --- /dev/null +++ b/generator/enum_string.tmpl @@ -0,0 +1,268 @@ +{{- define "enum_string"}} +const ( +{{- $enumName := .enum.Name -}} +{{- $enumType := .enum.Type -}} +{{- $vars := dict "lastoffset" "0" -}} +{{ range $rIndex, $value := .enum.Values }} + {{ if eq $value.Name "_"}}// Skipped value.{{else}}// {{$value.PrefixedName}} is a {{$enumName}} of type {{$value.RawName}}.{{end}} + {{- if $value.Comment}} + // {{$value.Comment}} + {{- end}} + {{$value.PrefixedName}} {{$enumName}} = "{{$value.RawName}}" +{{- end}} +) + +{{ if .names }}var _{{.enum.Name}}Names = {{namify .enum}} + +// {{.enum.Name}}Names returns a list of possible string values of {{.enum.Name}}. +func {{.enum.Name}}Names() []string { + tmp := make([]string, len(_{{.enum.Name}}Names)) + copy(tmp, _{{.enum.Name}}Names) + return tmp +} +{{ end -}} + +// String implements the Stringer interface. +func (x {{.enum.Name}}) String() string { + return string(x) +} + +// String implements the Stringer interface. +func (x {{.enum.Name}}) IsValid() bool { + _, err := Parse{{.enum.Name}}(string(x)) + return err == nil +} + +var _{{.enum.Name}}Value = {{ unmapify .enum .lowercase }} + +// Parse{{.enum.Name}} attempts to convert a string to a {{.enum.Name}}. +func Parse{{.enum.Name}}(name string) ({{.enum.Name}}, error) { + if x, ok := _{{.enum.Name}}Value[name]; ok { + return x, nil + }{{if .nocase }} + // Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to. + if x, ok := _{{.enum.Name}}Value[strings.ToLower(name)]; ok { + return x, nil + }{{- end}} + {{if .names -}} + return {{.enum.Name}}(""), fmt.Errorf("%s is not a valid {{.enum.Name}}, try [%s]", name, strings.Join(_{{.enum.Name}}Names, ", ")) + {{- else -}} + return {{.enum.Name}}(""), fmt.Errorf("%s is not a valid {{.enum.Name}}", name) + {{- end}} +} + +{{ if .mustparse }} +// MustParse{{.enum.Name}} converts a string to a {{.enum.Name}}, and panics if is not valid. +func MustParse{{.enum.Name}}(name string) {{.enum.Name}} { + val, err := Parse{{.enum.Name}}(name) + if err != nil { + panic(err) + } + return val +} +{{end}} + +{{ if .ptr }} +func (x {{.enum.Name}}) Ptr() *{{.enum.Name}} { + return &x +} +{{end}} + +{{ if .marshal }} +// MarshalText implements the text marshaller method. +func (x {{.enum.Name}}) MarshalText() ([]byte, error) { + return []byte(string(x)), nil +} + +// UnmarshalText implements the text unmarshaller method. +func (x *{{.enum.Name}}) UnmarshalText(text []byte) error { + tmp, err := Parse{{.enum.Name}}(string(text)) + if err != nil { + return err + } + *x = tmp + return nil +} +{{end}} + +{{ if or .sql .sqlnullint .sqlnullstr}} +var _{{.enum.Name}}ErrNilPtr = errors.New("value pointer is nil") // one per type for package clashes + +// Scan implements the Scanner interface. +func (x *{{.enum.Name}}) Scan(value interface{}) (err error) { + if value == nil { + *x = {{.enum.Name}}("") + return + } + + // A wider range of scannable types. + // driver.Value values at the top of the list for expediency + switch v := value.(type) { + case string: + *x, err = Parse{{.enum.Name}}(v) + case []byte: + *x, err = Parse{{.enum.Name}}(string(v)) + case {{.enum.Name}}: + *x = v + case *{{.enum.Name}}: + if v == nil{ + return _{{.enum.Name}}ErrNilPtr + } + *x = *v + case *string: + if v == nil{ + return _{{.enum.Name}}ErrNilPtr + } + *x, err = Parse{{.enum.Name}}(*v) + default: + return errors.New("invalid type for {{.enum.Name}}") + } + + return +} + +{{ if or .sql .sqlnullstr }} +// Value implements the driver Valuer interface. +func (x {{.enum.Name}}) Value() (driver.Value, error) { + return x.String(), nil +} +{{ else }} +// Value implements the driver Valuer interface. +func (x {{.enum.Name}}) Value() (driver.Value, error) { + return string(x), nil +} +{{end}} + +{{end}} + + +{{ if .flag }} +// Set implements the Golang flag.Value interface func. +func (x *{{.enum.Name}}) Set(val string) error { + v, err := Parse{{.enum.Name}}(val) + *x = v + return err +} + +// Get implements the Golang flag.Getter interface func. +func (x *{{.enum.Name}}) Get() interface{} { + return *x +} + +// Type implements the github.com/spf13/pFlag Value interface. +func (x *{{.enum.Name}}) Type() string { + return "{{.enum.Name}}" +} +{{end}} + +{{ if or .sqlnullint .sqlnullstr }} +type Null{{.enum.Name}} struct{ + {{.enum.Name}} {{.enum.Name}} + Valid bool{{/* Add some info as to whether this value was set during unmarshalling or not */}}{{if .marshal }} + Set bool{{ end }} +} + +func NewNull{{.enum.Name}}(val interface{}) (x Null{{.enum.Name}}) { + err := x.Scan(val) // yes, we ignore this error, it will just be an invalid value. + _ = err // make any errcheck linters happy + return +} + +// Scan implements the Scanner interface. +func (x *Null{{.enum.Name}}) Scan(value interface{}) (err error) { + if value == nil { + x.{{.enum.Name}}, x.Valid = {{.enum.Name}}(""), false + return + } + + err = x.{{.enum.Name}}.Scan(value) + x.Valid = (err == nil) + return +} + +{{ if .sqlnullint }} +// Value implements the driver Valuer interface. +func (x Null{{.enum.Name}}) Value() (driver.Value, error) { + if !x.Valid{ + return nil, nil + } + // driver.Value accepts int64 for int values. + return string(x.{{.enum.Name}}), nil +} +{{ else }} +// Value implements the driver Valuer interface. +func (x Null{{.enum.Name}}) Value() (driver.Value, error) { + if !x.Valid{ + return nil, nil + } + return x.{{.enum.Name}}.String(), nil +} +{{ end }} + +{{ if .marshal }} +// MarshalJSON correctly serializes a Null{{.enum.Name}} to JSON. +func (n Null{{.enum.Name}}) MarshalJSON() ([]byte, error) { + const nullStr = "null" + if n.Valid { + return json.Marshal(n.{{.enum.Name}}) + } + return []byte(nullStr), nil +} + +// UnmarshalJSON correctly deserializes a Null{{.enum.Name}} from JSON. +func (n *Null{{.enum.Name}}) UnmarshalJSON(b []byte) error { + n.Set = true + var x interface{} + err := json.Unmarshal(b, &x) + if err != nil{ + return err + } + err = n.Scan(x) + return err +} +{{ end }} + +{{ end }} + +{{ if and .sqlnullint .sqlnullstr }} +type Null{{.enum.Name}}Str struct { + Null{{.enum.Name}} +} + +func NewNull{{.enum.Name}}Str(val interface{}) (x Null{{.enum.Name}}Str) { + x.Scan(val) // yes, we ignore this error, it will just be an invalid value. + return +} + +// Value implements the driver Valuer interface. +func (x Null{{.enum.Name}}Str) Value() (driver.Value, error) { + if !x.Valid{ + return nil, nil + } + return x.{{.enum.Name}}.String(), nil +} +{{ if .marshal }} +// MarshalJSON correctly serializes a Null{{.enum.Name}} to JSON. +func (n Null{{.enum.Name}}Str) MarshalJSON() ([]byte, error) { + const nullStr = "null" + if n.Valid { + return json.Marshal(n.{{.enum.Name}}) + } + return []byte(nullStr), nil +} + +// UnmarshalJSON correctly deserializes a Null{{.enum.Name}} from JSON. +func (n *Null{{.enum.Name}}Str) UnmarshalJSON(b []byte) error { + n.Set = true + var x interface{} + err := json.Unmarshal(b, &x) + if err != nil{ + return err + } + err = n.Scan(x) + return err +} +{{ end }} +{{ end }} + +{{end}} diff --git a/generator/example_test.go b/generator/example_test.go index 4f094736..4248a31f 100644 --- a/generator/example_test.go +++ b/generator/example_test.go @@ -130,3 +130,11 @@ type Enum64bit uint64 // էժան = 1 // ) type NonASCII int + +// StringEnum. +// ENUM( +// random = 1114 +// values = 300 +// here = 1 +// ) +type StringEnum string diff --git a/generator/generator.go b/generator/generator.go index 111e8e0f..5b377b00 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -287,7 +287,12 @@ func (g *Generator) Generate(f *ast.File) ([]byte, error) { "forcelower": g.forceLower, } - err = g.t.ExecuteTemplate(vBuff, "enum", data) + templateName := "enum" + if enum.Type == "string" { + templateName = "enum_string" + } + + err = g.t.ExecuteTemplate(vBuff, templateName, data) if err != nil { return vBuff.Bytes(), errors.WithMessage(err, fmt.Sprintf("Failed writing enum data for enum: %q", name)) } diff --git a/generator/generator_1.18_test.go b/generator/generator_1.18_test.go index f061b0ee..9292b95f 100644 --- a/generator/generator_1.18_test.go +++ b/generator/generator_1.18_test.go @@ -261,7 +261,7 @@ func Test118EnumParseFailure(t *testing.T) { } // TestUintInvalidParsing -func TestUintInvalidParsing(t *testing.T) { +func Test118UintInvalidParsing(t *testing.T) { input := `package test // ENUM( // a=-1, diff --git a/generator/generator_test.go b/generator/generator_test.go index b2c605f2..f553c5a4 100644 --- a/generator/generator_test.go +++ b/generator/generator_test.go @@ -1,6 +1,3 @@ -//go:build !go1.18 -// +build !go1.18 - package generator import ( @@ -200,9 +197,7 @@ func TestAliasParsing(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - defer func() { - replacementNames = map[string]string{} - }() + replacementNames = map[string]string{} err := ParseAliases(tc.input) if tc.err != nil { require.Error(t, err) diff --git a/generator/template_funcs.go b/generator/template_funcs.go index dfec2238..493862c2 100644 --- a/generator/template_funcs.go +++ b/generator/template_funcs.go @@ -38,6 +38,9 @@ func Mapify(e Enum) (ret string, err error) { // Unmapify returns a map that is all of the indexes for a string value lookup func Unmapify(e Enum, lowercase bool) (ret string, err error) { + if e.Type == "string" { + return UnmapifyStringEnum(e, lowercase) + } strName := fmt.Sprintf(`_%sName`, e.Name) ret = fmt.Sprintf("map[string]%s{\n", e.Name) index := 0 @@ -55,8 +58,37 @@ func Unmapify(e Enum, lowercase bool) (ret string, err error) { return } +// Unmapify returns a map that is all of the indexes for a string value lookup +func UnmapifyStringEnum(e Enum, lowercase bool) (ret string, err error) { + var builder strings.Builder + _, err = builder.WriteString("map[string]" + e.Name + "{\n") + if err != nil { + return + } + for _, val := range e.Values { + if val.Name != skipHolder { + _, err = builder.WriteString(fmt.Sprintf("%q:%s,\n", val.RawName, val.PrefixedName)) + if err != nil { + return + } + if lowercase && strings.ToLower(val.RawName) != val.RawName { + _, err = builder.WriteString(fmt.Sprintf("%q:%s,\n", strings.ToLower(val.RawName), val.PrefixedName)) + if err != nil { + return + } + } + } + } + builder.WriteByte('}') + ret = builder.String() + return +} + // Namify returns a slice that is all of the possible names for an enum in a slice func Namify(e Enum) (ret string, err error) { + if e.Type == "string" { + return namifyStringEnum(e) + } strName := fmt.Sprintf(`_%sName`, e.Name) ret = "[]string{\n" index := 0 @@ -71,6 +103,18 @@ func Namify(e Enum) (ret string, err error) { return } +// Namify returns a slice that is all of the possible names for an enum in a slice +func namifyStringEnum(e Enum) (ret string, err error) { + ret = "[]string{\n" + for _, val := range e.Values { + if val.Name != skipHolder { + ret = fmt.Sprintf("%sstring(%s),\n", ret, val.PrefixedName) + } + } + ret = ret + "}" + return +} + func Offset(index int, enumType string, val EnumValue) (strResult string) { if strings.HasPrefix(enumType, "u") { // Unsigned diff --git a/go.mod b/go.mod index dda206db..bb65faeb 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/spf13/pflag v1.0.5 github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect diff --git a/go.sum b/go.sum index 018eb065..da3148fa 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=