├── .gitignore
├── .hgignore
├── .idea
├── codeStyles
│ └── codeStyleConfig.xml
├── enumeration.iml
├── go.imports.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
├── run
│ └── enumeration month.go.run.xml
├── runConfigurations
│ ├── enumeration_example_base.xml
│ ├── enumeration_example_channel.xml
│ ├── enumeration_example_day.xml
│ ├── enumeration_example_method.xml
│ ├── enumeration_example_month.xml
│ ├── enumeration_example_pet.xml
│ └── enumeration_season_json_nc_jj.xml
└── vcs.xml
├── LICENSE
├── README.md
├── build.sh
├── contributors.txt
├── enum
├── enum.go
├── enum_test.go
├── representation.go
└── representation_enum.go
├── enumeration.go
├── enumeration_test.go
├── example
├── base.go
├── base_enum.go
├── channel.go
├── channel_enum.go
├── country.go
├── country_enum.go
├── day.go
├── day_enum.go
├── example_test.go
├── greekalphabet.go
├── greekalphabet_enum.go
├── method.go
├── method_enum.go
├── month.go
├── month_enum.go
├── pet.go
└── pet_enum.go
├── go.mod
├── go.sum
├── internal
├── codegen
│ ├── units.go
│ └── units_test.go
├── collection
│ ├── set.go
│ └── set_test.go
├── model
│ ├── model.go
│ ├── write.go
│ ├── write_core.go
│ └── write_test.go.txt
├── parse
│ ├── convert.go
│ ├── convert_test.go
│ ├── parse_const.go
│ ├── parse_type.go
│ └── scanner.go
├── test
│ ├── combination_test.go
│ ├── combinations.xlsx
│ ├── season.go
│ ├── season1_enum.go
│ ├── season2_enum.go
│ ├── season_ic_ji_enum.go
│ ├── season_ic_jj_enum.go
│ ├── season_ic_jn_enum.go
│ ├── season_ic_si_enum.go
│ ├── season_ic_sn_enum.go
│ ├── season_ic_ss_enum.go
│ ├── season_ic_ta_enum.go
│ ├── season_ic_ti_enum.go
│ ├── season_ic_tn_enum.go
│ ├── season_ic_tt_enum.go
│ ├── season_json.go
│ ├── season_nc_ji_enum.go
│ ├── season_nc_jj_enum.go
│ ├── season_nc_jn_enum.go
│ ├── season_nc_si_enum.go
│ ├── season_nc_sn_enum.go
│ ├── season_nc_ss_enum.go
│ ├── season_nc_ta_enum.go
│ ├── season_nc_ti_enum.go
│ ├── season_nc_tn_enum.go
│ ├── season_nc_tt_enum.go
│ ├── season_sql.go
│ ├── season_text.go
│ ├── season_uc_ji_enum.go
│ ├── season_uc_jj_enum.go
│ ├── season_uc_jn_enum.go
│ ├── season_uc_si_enum.go
│ ├── season_uc_sn_enum.go
│ ├── season_uc_ta_enum.go
│ ├── season_uc_ti_enum.go
│ ├── season_uc_tn_enum.go
│ ├── season_uc_tt_enum.go
│ └── simple
│ │ ├── season_json.go
│ │ ├── season_sql.go
│ │ └── season_text.go
├── transform
│ ├── case.go
│ ├── case_enum.go
│ └── unsnake.go
└── util
│ └── util.go
├── magefiles
└── build.go
└── version.go
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/shelf/
2 | .idea/workspace.xml
3 | /bin/
4 | /temp/
5 | /go.work
6 | /go.work.sum
7 |
--------------------------------------------------------------------------------
/.hgignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/enumeration.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/go.imports.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/run/enumeration month.go.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_channel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_day.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_method.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_month.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_example_pet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/enumeration_season_json_nc_jj.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, Rick Beton
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of enumeration nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -ex
2 | cd "$(dirname "$0")"
3 | go install tool
4 | mage
5 |
--------------------------------------------------------------------------------
/contributors.txt:
--------------------------------------------------------------------------------
1 | Rick Beton
2 |
--------------------------------------------------------------------------------
/enum/enum.go:
--------------------------------------------------------------------------------
1 | // Package enum provides an API for manipulating enumerations.
2 | // This is support code for the auto-generated enumerations:
3 | // see https://github.com/rickb777/enumeration for further instructions.
4 | package enum
5 |
6 | // Enum is a generic contract for all generated enums.
7 | type Enum interface {
8 | Ordinal() int
9 | String() string
10 | IsValid() bool
11 | }
12 |
13 | // IntEnum is a specialisation for those enums that have int or similar as the underlying type.
14 | type IntEnum interface {
15 | Enum
16 | Int() int
17 | }
18 |
19 | // FloatEnum is a specialisation for those enums that have float32 or float64 as the underlying type.
20 | type FloatEnum interface {
21 | Enum
22 | Float() float64
23 | }
24 |
25 | //-------------------------------------------------------------------------------------------------
26 |
27 | // Enums is a slice of Enum.
28 | type Enums []Enum
29 |
30 | // Strings gets the string values of the enums in the same order.
31 | func (es Enums) Strings() []string {
32 | ss := make([]string, len(es))
33 | for i, e := range es {
34 | ss[i] = e.String()
35 | }
36 | return ss
37 | }
38 |
39 | // Ordinals gets the ordinal values of the enums in the same order.
40 | func (es Enums) Ordinals() []int {
41 | os := make([]int, len(es))
42 | for i, e := range es {
43 | os[i] = e.Ordinal()
44 | }
45 | return os
46 | }
47 |
48 | //-------------------------------------------------------------------------------------------------
49 |
50 | // IntEnums is a slice of IntEnum.
51 | type IntEnums []IntEnum
52 |
53 | // Strings gets the string values of the enums in the same order.
54 | func (es IntEnums) Strings() []string {
55 | ss := make([]string, len(es))
56 | for i, e := range es {
57 | ss[i] = e.String()
58 | }
59 | return ss
60 | }
61 |
62 | // Ordinals gets the ordinal values of the enums in the same order.
63 | func (es IntEnums) Ordinals() []int {
64 | os := make([]int, len(es))
65 | for i, e := range es {
66 | os[i] = e.Ordinal()
67 | }
68 | return os
69 | }
70 |
71 | // Ints gets the values of the enums in the same order.
72 | func (es IntEnums) Ints() []int {
73 | vs := make([]int, len(es))
74 | for i, e := range es {
75 | vs[i] = e.Int()
76 | }
77 | return vs
78 | }
79 |
80 | //-------------------------------------------------------------------------------------------------
81 |
82 | // FloatEnums is a slice of FloatEnum.
83 | type FloatEnums []FloatEnum
84 |
85 | // Strings gets the string values of the enums in the same order.
86 | func (es FloatEnums) Strings() []string {
87 | ss := make([]string, len(es))
88 | for i, e := range es {
89 | ss[i] = e.String()
90 | }
91 | return ss
92 | }
93 |
94 | // Ordinals gets the ordinal values of the enums in the same order.
95 | func (es FloatEnums) Ordinals() []int {
96 | os := make([]int, len(es))
97 | for i, e := range es {
98 | os[i] = e.Ordinal()
99 | }
100 | return os
101 | }
102 |
103 | // Floats gets the values of the enums in the same order.
104 | func (es FloatEnums) Floats() []float64 {
105 | vs := make([]float64, len(es))
106 | for i, e := range es {
107 | vs[i] = e.Float()
108 | }
109 | return vs
110 | }
111 |
112 | func QuotedString(s string) []byte {
113 | b := make([]byte, len(s)+2)
114 | b[0] = '"'
115 | copy(b[1:], s)
116 | b[len(s)+1] = '"'
117 | return b
118 | }
119 |
--------------------------------------------------------------------------------
/enum/enum_test.go:
--------------------------------------------------------------------------------
1 | package enum_test
2 |
3 | import (
4 | "github.com/rickb777/expect"
5 | "strings"
6 | "testing"
7 |
8 | "github.com/rickb777/enumeration/v4/enum"
9 | "github.com/rickb777/enumeration/v4/example"
10 | )
11 |
12 | func TestIntEnums_Strings(t *testing.T) {
13 | methods := example.AllMethodEnums.Strings()
14 |
15 | expect.String(strings.Join(methods, "|")).ToBe(t, "HEAD|GET|PUT|POST|PATCH|DELETE")
16 |
17 | methods = enum.Enums{example.HEAD, example.PUT, example.PATCH}.Strings()
18 |
19 | expect.String(strings.Join(methods, "|")).ToBe(t, "HEAD|PUT|PATCH")
20 | }
21 |
22 | func TestIntEnums_Ordinals(t *testing.T) {
23 | days := enum.Enums{example.Wednesday, example.Friday, example.Sunday}.Ordinals()
24 |
25 | expect.Slice(days).ToBe(t, 3, 5, 0)
26 |
27 | days = enum.IntEnums{example.Wednesday, example.Friday, example.Sunday}.Ordinals()
28 |
29 | expect.Slice(days).ToBe(t, 3, 5, 0)
30 | }
31 |
32 | func TestIntEnums_Ints(t *testing.T) {
33 | days := enum.IntEnums{example.Wednesday, example.Friday, example.Sunday}.Ints()
34 |
35 | expect.Slice(days).ToBe(t, 4, 6, 1)
36 | }
37 |
38 | //-------------------------------------------------------------------------------------------------
39 |
40 | func TestFloatEnums_Strings(t *testing.T) {
41 | es := example.AllBaseEnums.Strings()
42 |
43 | expect.Slice(es).ToBe(t, "a", "c", "g", "t")
44 | }
45 |
46 | func TestFloatEnums_Ordinals(t *testing.T) {
47 | es := enum.Enums{example.C, example.T}.Ordinals()
48 |
49 | expect.Slice(es).ToBe(t, 1, 3)
50 |
51 | es = enum.FloatEnums{example.C, example.T}.Ordinals()
52 |
53 | expect.Slice(es).ToBe(t, 1, 3)
54 | }
55 |
56 | func TestFloatEnums_Floats(t *testing.T) {
57 | es := example.AllBaseEnums.Floats()
58 |
59 | expect.Slice(es).ToBe(t, float64(example.A), float64(example.C), float64(example.G), float64(example.T))
60 | }
61 |
62 | func TestQuotedString(t *testing.T) {
63 | qs1 := enum.QuotedString("")
64 | expect.String(qs1).ToBe(t, []byte{'"', '"'})
65 |
66 | qs2 := enum.QuotedString("XYZ")
67 | expect.String(qs2).ToBe(t, []byte{'"', 'X', 'Y', 'Z', '"'})
68 | }
69 |
70 | func TestRepresentation(t *testing.T) {
71 | r1 := enum.MustParseRepresentation("number")
72 | expect.Number(r1).ToBe(t, enum.Number)
73 |
74 | r2 := enum.MustParseRepresentation("2")
75 | expect.Number(r2).ToBe(t, enum.Number)
76 |
77 | _, err := enum.AsRepresentation("foobar")
78 | expect.Error(err).ToHaveOccurred(t)
79 |
80 | num := enum.Number.String()
81 | expect.String(num).ToBe(t, "Number")
82 |
83 | o1 := enum.RepresentationOf(1)
84 | expect.Number(o1).ToBe(t, enum.Identifier)
85 | expect.Number(o1.Int()).ToBe(t, 1)
86 | expect.Bool(o1.IsValid()).ToBeTrue(t)
87 |
88 | o3 := enum.RepresentationOf(3)
89 | expect.Number(o1.Int()).ToBe(t, 1)
90 | expect.Bool(o3.IsValid()).ToBeFalse(t)
91 |
92 | expect.Bool(enum.None.IsValid()).ToBeTrue(t)
93 | expect.Bool(enum.Representation(4).IsValid()).ToBeFalse(t)
94 | expect.String(enum.Representation(4).String()).ToBe(t, "Representation(4)")
95 | }
96 |
--------------------------------------------------------------------------------
/enum/representation.go:
--------------------------------------------------------------------------------
1 | package enum
2 |
3 | //go:generate enumeration -type Representation -ic -alias altReps
4 |
5 | type Representation int
6 |
7 | const (
8 | None Representation = iota // disables the feature (new in v3)
9 | Identifier // uses the main identifier of the corresponding constant
10 | Number // the value of the enumerant as a decimal number
11 | )
12 |
13 | var altReps = map[string]Representation{
14 | "x": None,
15 | "id": Identifier,
16 | "num": Number,
17 | "n": Number,
18 | }
19 |
--------------------------------------------------------------------------------
/enum/representation_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4
3 |
4 | package enum
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllRepresentations lists all 3 values in order.
15 | var AllRepresentations = []Representation{
16 | None, Identifier, Number,
17 | }
18 |
19 | const (
20 | representationEnumStrings = "NoneIdentifierNumber"
21 | representationEnumInputs = "noneidentifiernumber"
22 | )
23 |
24 | var (
25 | representationEnumIndex = [...]uint16{0, 4, 14, 20}
26 | )
27 |
28 | // Ordinal returns the ordinal number of a Representation. This is an integer counting
29 | // from zero. It is *not* the same as the const number assigned to the value.
30 | func (v Representation) Ordinal() int {
31 | switch v {
32 | case None:
33 | return 0
34 | case Identifier:
35 | return 1
36 | case Number:
37 | return 2
38 | }
39 | return -1
40 | }
41 |
42 | // String returns the literal string representation of a Representation, which is
43 | // the same as the const identifier but without prefix or suffix.
44 | func (v Representation) String() string {
45 | o := v.Ordinal()
46 | return v.toString(o, representationEnumStrings, representationEnumIndex[:])
47 | }
48 |
49 | func (v Representation) toString(o int, concats string, indexes []uint16) string {
50 | if o < 0 || o >= len(AllRepresentations) {
51 | return fmt.Sprintf("Representation(%d)", v)
52 | }
53 | return concats[indexes[o]:indexes[o+1]]
54 | }
55 |
56 | // IsValid determines whether a Representation is one of the defined constants.
57 | func (v Representation) IsValid() bool {
58 | return v.Ordinal() >= 0
59 | }
60 |
61 | // Int returns the int value, which is not necessarily the same as the ordinal.
62 | // This facilitates polymorphism (see enum.IntEnum).
63 | func (v Representation) Int() int {
64 | return int(v)
65 | }
66 |
67 | var invalidRepresentationValue = func() Representation {
68 | var v Representation
69 | for {
70 | if !slices.Contains(AllRepresentations, v) {
71 | return v
72 | }
73 | v++
74 | } // AllRepresentations is a finite set so loop will terminate eventually
75 | }()
76 |
77 | // RepresentationOf returns a Representation based on an ordinal number. This is the inverse of Ordinal.
78 | // If the ordinal is out of range, an invalid Representation is returned.
79 | func RepresentationOf(v int) Representation {
80 | if 0 <= v && v < len(AllRepresentations) {
81 | return AllRepresentations[v]
82 | }
83 | return invalidRepresentationValue
84 | }
85 |
86 | // Parse parses a string to find the corresponding Representation, accepting one of the string values or
87 | // a number. It is used by AsRepresentation.
88 | // The input case does not matter.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Representation)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Representation) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := representationTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Representation) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Representation(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Representation) parseFallback(in, s string) error {
117 | if v.parseString(s, representationEnumInputs, representationEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | var ok bool
122 | *v, ok = altReps[s]
123 | if ok {
124 | return nil
125 | }
126 |
127 | return errors.New(in + ": unrecognised representation")
128 | }
129 |
130 | func (v *Representation) parseString(s string, concats string, indexes []uint16) (ok bool) {
131 | var i0 uint16 = 0
132 |
133 | for j := 1; j < len(indexes); j++ {
134 | i1 := indexes[j]
135 | p := concats[i0:i1]
136 | if s == p {
137 | *v = AllRepresentations[j-1]
138 | return true
139 | }
140 | i0 = i1
141 | }
142 | *v, ok = altReps[s]
143 | return ok
144 | }
145 |
146 | // representationTransformInput may alter input strings before they are parsed.
147 | // This function is pluggable and is initialised using command-line flags
148 | // -ic -lc -uc -unsnake.
149 | var representationTransformInput = func(in string) string {
150 | return strings.ToLower(in)
151 | }
152 |
153 | // AsRepresentation parses a string to find the corresponding Representation, accepting either one of the string values or
154 | // a number. It wraps Parse.
155 | // The input case does not matter.
156 | func AsRepresentation(s string) (Representation, error) {
157 | var v = new(Representation)
158 | err := v.Parse(s)
159 | return *v, err
160 | }
161 |
162 | // MustParseRepresentation is similar to AsRepresentation except that it panics on error.
163 | // The input case does not matter.
164 | func MustParseRepresentation(s string) Representation {
165 | v, err := AsRepresentation(s)
166 | if err != nil {
167 | panic(err)
168 | }
169 | return v
170 | }
171 |
--------------------------------------------------------------------------------
/enumeration.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "io"
7 | "os"
8 | "path/filepath"
9 | "strings"
10 |
11 | "github.com/rickb777/enumeration/v4/enum"
12 | "github.com/rickb777/enumeration/v4/internal/model"
13 | "github.com/rickb777/enumeration/v4/internal/parse"
14 | "github.com/rickb777/enumeration/v4/internal/transform"
15 | "github.com/rickb777/enumeration/v4/internal/util"
16 | )
17 |
18 | var config model.Config
19 | var inputGo, outputGo, outputJSON, marshalTextRep, marshalJSONRep, storeRep string
20 | var force, nocase, lowercase, uppercase, showVersion bool
21 |
22 | func defineFlags() {
23 | flag.StringVar(&config.MainType, "type", "", "Name of the enumeration type (required).")
24 | flag.StringVar(&model.Prefix, "prefix", "", "Optional prefix to be stripped from the identifiers.")
25 | flag.StringVar(&model.Suffix, "suffix", "", "Optional suffix to be stripped from the identifiers.")
26 | flag.StringVar(&inputGo, "i", "", "Name of the input file. May be '-' for stdin. Default is enumeration type in lower case.")
27 | flag.StringVar(&outputGo, "o", "", "Name of the output file. May be '-' for stdout. Default is enumeration type in lower case plus '_enum'.")
28 | flag.StringVar(&config.Plural, "plural", "", "Plural name of the enumeration type (optional).")
29 | flag.StringVar(&parse.AliasTable, "alias", "", "Uses your own map[string]Type as aliases during parsing.")
30 | flag.StringVar(&config.Pkg, "package", "", "Name of the output package (optional). Defaults to the output directory.")
31 | flag.StringVar(&marshalTextRep, "marshaltext", "None", "Marshal text values using Identifier or Number")
32 | flag.StringVar(&marshalJSONRep, "marshaljson", "None", "Marshal JSON values using Identifier or Number")
33 | flag.StringVar(&storeRep, "store", "None", "Store values in a DB using Identifier, Number or Ordinal")
34 |
35 | flag.BoolVar(&config.Lenient, "lenient", false, "Allow parsing to yield invalid values.")
36 | flag.BoolVar(&force, "f", false, "Force writing the output file even if up to date (not used when piping stdin or stdout).")
37 | flag.BoolVar(&nocase, "nc", false, "Don't convert strings to upper or lowercase (this is the default)")
38 | flag.BoolVar(&lowercase, "lc", false, "Convert strings to lowercase and ignore case when parsing")
39 | flag.BoolVar(&uppercase, "uc", false, "Convert strings to uppercase and ignore case when parsing.")
40 | flag.BoolVar(&config.IgnoreCase, "ic", false, "Ignore case when parsing but keep the mixed case when outputting.")
41 | flag.BoolVar(&config.Unsnake, "unsnake", false, "Convert underscores in identifiers to spaces.")
42 | flag.BoolVar(&config.SimpleOnly, "s", false, "Generate simple enumerations without serialising or parsing functions")
43 | flag.BoolVar(&config.Polymorphic, "poly", false, "Generate polymorphic representation code")
44 | flag.BoolVar(&util.Verbose, "v", false, "Verbose progress messages.")
45 | flag.BoolVar(&util.Dbg, "z", false, "Debug messages.")
46 | flag.BoolVar(&showVersion, "version", false, "Print version number.")
47 | }
48 |
49 | func choosePackage(outputFile string) string {
50 | wd, err := os.Getwd()
51 | if err != nil {
52 | util.Fail(err)
53 | }
54 |
55 | dir := filepath.Base(filepath.Dir(outputFile))
56 |
57 | if dir != "." {
58 | return dir
59 | }
60 |
61 | return filepath.Base(filepath.FromSlash(wd))
62 | }
63 |
64 | func notUpToDate() bool {
65 | if inputGo != "-" && outputGo != "-" {
66 | xi, err := os.Stat(inputGo)
67 | if err == nil {
68 | xo, err := os.Stat(outputGo)
69 | if err == nil && xo.ModTime().After(xi.ModTime()) {
70 | util.Info("Skipped %s.\n", outputGo)
71 | return false
72 | }
73 | }
74 | }
75 | return true
76 | }
77 |
78 | func generate() {
79 | util.Debug("ReadFile %s\n", inputGo)
80 | var err error
81 | config.MarshalTextRep, err = enum.AsRepresentation(marshalTextRep)
82 | util.Must(err, "(-marshaltext)")
83 |
84 | config.MarshalJSONRep, err = enum.AsRepresentation(marshalJSONRep)
85 | util.Must(err, "(-marshaljson)")
86 |
87 | config.StoreRep, err = enum.AsRepresentation(storeRep)
88 | util.Must(err, "(-store)")
89 |
90 | var in io.Reader = os.Stdin
91 | if inputGo != "-" {
92 | inf, e2 := os.Open(inputGo)
93 | util.Must(e2)
94 | defer inf.Close()
95 | in = inf
96 | }
97 |
98 | var out model.DualWriter = os.Stdout
99 | if outputGo == "-" {
100 | if config.Pkg == "" {
101 | util.Fail("-pkg is required when piping the output.")
102 | }
103 | } else {
104 | outf, e2 := os.Create(outputGo)
105 | util.Must(e2)
106 | defer outf.Close()
107 | out = outf
108 | config.Pkg = choosePackage(outputGo)
109 | util.Stdout = os.Stdout // ok because it's not going to be interleaved now
110 | }
111 | util.Debug("pkg=%s\n", config.Pkg)
112 |
113 | xCase := transform.Of(lowercase, uppercase)
114 |
115 | m, err := parse.Convert(in, inputGo, xCase, config)
116 | util.Must(err)
117 |
118 | units := m.BuildUnits()
119 | model.WriteGo(units, m, out)
120 | util.Info("Generated %s.\n", outputGo)
121 | }
122 |
123 | func main() {
124 | defineFlags()
125 | flag.Parse()
126 | doMain()
127 | }
128 |
129 | func doMain() {
130 | config.Version = appVersion
131 |
132 | if showVersion {
133 | fmt.Fprintln(os.Stdout, appVersion)
134 | os.Exit(0)
135 | }
136 |
137 | if config.MainType == "" {
138 | util.Fail("Must specify -type.")
139 | }
140 |
141 | if config.Plural == "" {
142 | config.Plural = config.MainType + "s"
143 | }
144 |
145 | if inputGo == "" {
146 | inputGo = strings.ToLower(config.MainType) + ".go"
147 | }
148 |
149 | if outputGo == "" {
150 | outputGo = strings.ToLower(config.MainType) + "_enum.go"
151 | } else if outputGo == "-" {
152 | util.Stdout = os.Stderr // avoiding interleaving with the output of generated code
153 | }
154 |
155 | if outputJSON == "" {
156 | outputJSON = strings.ToLower(config.MainType) + "_enum.json"
157 | }
158 |
159 | if config.SimpleOnly {
160 | config.IgnoreCase = false
161 | config.Lenient = false
162 | }
163 |
164 | util.Debug("type=%s\n", config.MainType)
165 | util.Debug("plural=%s\n", config.Plural)
166 | util.Debug("inputGo=%s\n", inputGo)
167 | util.Debug("outputGo=%s\n", outputGo)
168 | util.Debug("outputJSON=%s\n", outputJSON)
169 |
170 | if force || notUpToDate() {
171 | generate()
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/enumeration_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/rickb777/enumeration/v4/internal/model"
6 | "github.com/rickb777/enumeration/v4/internal/parse"
7 | "github.com/rickb777/expect"
8 | "go/scanner"
9 | "go/token"
10 | "io"
11 | "os"
12 | "strings"
13 | "testing"
14 | )
15 |
16 | func TestMainApp_Day(t *testing.T) {
17 | outputFile := "temp/example/day_enum.go"
18 |
19 | remove(t, outputGo)
20 |
21 | os.Args = []string{"", "-f", "-type", "Day", "-i", "temp/example/day.go", "-o", outputFile}
22 |
23 | main()
24 |
25 | compareGeneratedFile(t, outputFile)
26 | }
27 |
28 | func TestMainApp_Channel(t *testing.T) {
29 | inputGo = "temp/example/channel.go"
30 | outputGo = "temp/example/channel_enum.go"
31 |
32 | remove(t, outputGo)
33 |
34 | force = true
35 | lowercase, uppercase, showVersion = false, false, false
36 | outputJSON, marshalTextRep, marshalJSONRep, storeRep = "", "None", "None", "None"
37 |
38 | model.Prefix = ""
39 | model.Suffix = "Sales"
40 | parse.AliasTable = ""
41 |
42 | config = model.Config{
43 | MainType: "SalesChannel",
44 | }
45 |
46 | doMain()
47 |
48 | compareGeneratedFile(t, outputGo)
49 | }
50 |
51 | func TestMainApp_Country(t *testing.T) {
52 | inputGo = "temp/example/country.go"
53 | outputGo = "temp/example/country_enum.go"
54 |
55 | remove(t, outputGo)
56 |
57 | force = true
58 | lowercase, uppercase, showVersion = false, false, false
59 | outputJSON, marshalTextRep, marshalJSONRep, storeRep = "", "None", "None", "Number"
60 |
61 | model.Prefix = ""
62 | model.Suffix = ""
63 | parse.AliasTable = "iso3166_3LetterCodes"
64 |
65 | config = model.Config{
66 | MainType: "Country",
67 | Plural: "Countries",
68 | IgnoreCase: true,
69 | Unsnake: true,
70 | }
71 |
72 | doMain()
73 |
74 | compareGeneratedFile(t, outputGo)
75 | }
76 |
77 | func TestMainApp_Method(t *testing.T) {
78 | inputGo = "temp/example/method.go"
79 | outputGo = "temp/example/method_enum.go"
80 |
81 | remove(t, outputGo)
82 |
83 | force = true
84 | lowercase, uppercase, showVersion = false, false, false
85 | outputJSON, marshalTextRep, marshalJSONRep, storeRep = "", "None", "None", "Number"
86 |
87 | model.Prefix = ""
88 | model.Suffix = ""
89 | parse.AliasTable = ""
90 |
91 | config = model.Config{
92 | MainType: "Method",
93 | IgnoreCase: true,
94 | }
95 |
96 | doMain()
97 |
98 | compareGeneratedFile(t, outputGo)
99 | }
100 |
101 | func remove(t *testing.T, file string) {
102 | err := os.Remove(file)
103 | if err != nil {
104 | t.Logf("rm %s: %s", file, err.Error())
105 | // continue anyway
106 | }
107 | }
108 |
109 | func compareGeneratedFile(t *testing.T, fileName string) {
110 | src, err := os.ReadFile(fileName)
111 | expect.Error(err).Not().ToHaveOccurred(t)
112 |
113 | var s scanner.Scanner
114 | fset := token.NewFileSet() // positions are relative to fset
115 | file := fset.AddFile("", fset.Base(), len(src)) // register input "file"
116 | s.Init(file, src, nil /* no error handler */, scanner.ScanComments)
117 |
118 | // check just the first few lines of the generated Go source code
119 |
120 | pos, tok, lit := s.Scan()
121 | expect.Number(tok).ToBe(t, token.COMMENT)
122 |
123 | _, tok, lit = s.Scan()
124 | expect.Number(tok).ToBe(t, token.COMMENT)
125 |
126 | _, tok, lit = s.Scan()
127 | expect.Number(tok).ToBe(t, token.PACKAGE)
128 |
129 | _, tok, lit = s.Scan()
130 | expect.Number(tok).ToBe(t, token.IDENT)
131 | expect.String(lit).ToBe(t, "example")
132 |
133 | _, tok, lit = s.Scan()
134 | expect.Number(tok).ToBe(t, token.SEMICOLON)
135 |
136 | _, tok, lit = s.Scan()
137 | expect.Number(tok).ToBe(t, token.IMPORT)
138 |
139 | _, tok, lit = s.Scan()
140 | expect.Number(tok).ToBe(t, token.LPAREN)
141 |
142 | if testing.Verbose() {
143 | for {
144 | pos, tok, lit = s.Scan()
145 | if tok == token.EOF {
146 | break
147 | }
148 | fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
149 | }
150 | }
151 | }
152 |
153 | func TestScannerTryOut(t *testing.T) {
154 | if testing.Verbose() {
155 | for _, n := range []string{"example/base.go", "example/day.go", "example/country.go", "example/month.go"} {
156 | f, err := os.Open(n)
157 | expect.Error(err).Not().ToHaveOccurred(t)
158 | defer f.Close()
159 |
160 | fmt.Printf("-- %s\n", n)
161 | src, err := io.ReadAll(f)
162 | expect.Error(err).Not().ToHaveOccurred(t)
163 |
164 | var s scanner.Scanner
165 | fset := token.NewFileSet() // positions are relative to fset
166 | file := fset.AddFile("", fset.Base(), len(src)) // register input "file"
167 | s.Init(file, src, nil /* no error handler */, 0)
168 |
169 | for {
170 | pos, tok, lit := s.Scan()
171 | if tok == token.EOF {
172 | break
173 | }
174 | fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
175 | }
176 | fmt.Printf("%s\n", strings.Repeat("-", 80))
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/example/base.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -f -type Base -lc -poly
4 |
5 | // Base example demonstrates using floating point values instead of integers.
6 | // These are float32 but could be float64; the only other restriction is that
7 | // no two values can be the same number.
8 | type Base float32
9 |
10 | // Nucleotide Molecular Weights, g/mol
11 | const A Base = 331.2
12 | const C Base = 307.2
13 | const G Base = 347.2
14 | const T Base = 322.2
15 |
--------------------------------------------------------------------------------
/example/base_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package example
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "github.com/rickb777/enumeration/v4/enum"
10 | "slices"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | // AllBases lists all 4 values in order.
16 | var AllBases = []Base{
17 | A, C, G, T,
18 | }
19 |
20 | // AllBaseEnums lists all 4 values in order.
21 | var AllBaseEnums = enum.FloatEnums{
22 | A, C, G, T,
23 | }
24 |
25 | const (
26 | baseEnumStrings = "acgt"
27 | )
28 |
29 | var (
30 | baseEnumIndex = [...]uint16{0, 1, 2, 3, 4}
31 | )
32 |
33 | // String returns the literal string representation of a Base, which is
34 | // the same as the const identifier but without prefix or suffix.
35 | func (v Base) String() string {
36 | o := v.Ordinal()
37 | return v.toString(o, baseEnumStrings, baseEnumIndex[:])
38 | }
39 |
40 | // Ordinal returns the ordinal number of a Base. This is an integer counting
41 | // from zero. It is *not* the same as the const number assigned to the value.
42 | func (v Base) Ordinal() int {
43 | switch v {
44 | case A:
45 | return 0
46 | case C:
47 | return 1
48 | case G:
49 | return 2
50 | case T:
51 | return 3
52 | }
53 | return -1
54 | }
55 |
56 | func (v Base) toString(o int, concats string, indexes []uint16) string {
57 | if o < 0 || o >= len(AllBases) {
58 | return fmt.Sprintf("Base(%g)", v)
59 | }
60 | return concats[indexes[o]:indexes[o+1]]
61 | }
62 |
63 | // IsValid determines whether a Base is one of the defined constants.
64 | func (v Base) IsValid() bool {
65 | return v.Ordinal() >= 0
66 | }
67 |
68 | // Float returns the float64 value. It serves to facilitate polymorphism (see enum.FloatEnum).
69 | func (v Base) Float() float64 {
70 | return float64(v)
71 | }
72 |
73 | var invalidBaseValue = func() Base {
74 | var v Base
75 | for {
76 | if !slices.Contains(AllBases, v) {
77 | return v
78 | }
79 | v++
80 | } // AllBases is a finite set so loop will terminate eventually
81 | }()
82 |
83 | // BaseOf returns a Base based on an ordinal number. This is the inverse of Ordinal.
84 | // If the ordinal is out of range, an invalid Base is returned.
85 | func BaseOf(v int) Base {
86 | if 0 <= v && v < len(AllBases) {
87 | return AllBases[v]
88 | }
89 | return invalidBaseValue
90 | }
91 |
92 | // Parse parses a string to find the corresponding Base, accepting one of the string values or
93 | // a number. It is used by AsBase.
94 | //
95 | // Usage Example
96 | //
97 | // v := new(Base)
98 | // err := v.Parse(s)
99 | // ... etc
100 | func (v *Base) Parse(in string) error {
101 | if v.parseNumber(in) {
102 | return nil
103 | }
104 |
105 | s := baseTransformInput(in)
106 |
107 | return v.parseFallback(in, s)
108 | }
109 |
110 | // parseNumber attempts to convert a decimal value.
111 | // Only numbers that correspond to the enumeration are valid.
112 | func (v *Base) parseNumber(s string) (ok bool) {
113 | num, err := strconv.ParseFloat(s, 64)
114 | if err == nil {
115 | *v = Base(num)
116 | return v.IsValid()
117 | }
118 | return false
119 | }
120 |
121 | func (v *Base) parseFallback(in, s string) error {
122 | if v.parseString(s, baseEnumStrings, baseEnumIndex[:]) {
123 | return nil
124 | }
125 |
126 | return errors.New(in + ": unrecognised base")
127 | }
128 |
129 | func (v *Base) parseString(s string, concats string, indexes []uint16) (ok bool) {
130 | var i0 uint16 = 0
131 |
132 | for j := 1; j < len(indexes); j++ {
133 | i1 := indexes[j]
134 | p := concats[i0:i1]
135 | if s == p {
136 | *v = AllBases[j-1]
137 | return true
138 | }
139 | i0 = i1
140 | }
141 | return false
142 | }
143 |
144 | // baseTransformInput may alter input strings before they are parsed.
145 | // This function is pluggable and is initialised using command-line flags
146 | // -ic -lc -uc -unsnake.
147 | var baseTransformInput = func(in string) string {
148 | return strings.ToLower(in)
149 | }
150 |
151 | // AsBase parses a string to find the corresponding Base, accepting either one of the string values or
152 | // a number. It wraps Parse.
153 | func AsBase(s string) (Base, error) {
154 | var v = new(Base)
155 | err := v.Parse(s)
156 | return *v, err
157 | }
158 |
159 | // MustParseBase is similar to AsBase except that it panics on error.
160 | func MustParseBase(s string) Base {
161 | v, err := AsBase(s)
162 | if err != nil {
163 | panic(err)
164 | }
165 | return v
166 | }
167 |
--------------------------------------------------------------------------------
/example/channel.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -i channel.go -o channel_enum.go -lc -type SalesChannel -suffix Sales -poly
4 |
5 | // preamble const declarations are ignored by the enumeration tool
6 | const IgnoreThisItem, AndThis = 741, "quack"
7 |
8 | const (
9 | // One is ignored by the enumeration tool too
10 | One = 1
11 | )
12 |
13 | // SalesChannel example demonstrates the removing of a suffix string from the identifiers
14 | // when their string equivalent is accessed.
15 | //
16 | // The `json` tags in comments control values used for JSON marshalling.
17 | // The `sql` tags in comments control values used for SQL storage.
18 | type SalesChannel int
19 |
20 | const (
21 | OnlineSales SalesChannel = 3 // json:"webshop" sql:"o" -- String() is "online"
22 | InstoreSales SalesChannel = 5 // json:"store" sql:"s" -- String() is "instore"
23 | TelephoneSales SalesChannel = 7 // json:"phone" sql:"t" -- String() is "telephone"
24 | )
25 |
--------------------------------------------------------------------------------
/example/day.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -type Day
4 |
5 | // Day simple example also shows that more than one 'const' block can be used
6 | // provided that the integer values are all distinct.
7 | type Day uint
8 |
9 | const (
10 | _ Day = iota // throw away zeroth so that Sunday is 1
11 | Sunday
12 | Monday
13 | Tuesday
14 | Wednesday
15 | )
16 |
17 | // It is allowable to break the constant blocks (although it's a bit
18 | // unnecessary here). However, the numeric values *must* all be distinct,
19 | // otherwise the generated enum will not compile.
20 | const (
21 | Thursday Day = iota + 5
22 | Friday
23 | Saturday
24 | numberOfDays = int(Saturday) // this is not exported
25 | )
26 |
--------------------------------------------------------------------------------
/example/day_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package example
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllDays lists all 7 values in order.
14 | var AllDays = []Day{
15 | Sunday, Monday, Tuesday, Wednesday,
16 | Thursday, Friday, Saturday,
17 | }
18 |
19 | const (
20 | dayEnumStrings = "SundayMondayTuesdayWednesdayThursdayFridaySaturday"
21 | )
22 |
23 | var (
24 | dayEnumIndex = [...]uint16{0, 6, 12, 19, 28, 36, 42, 50}
25 | )
26 |
27 | // String returns the literal string representation of a Day, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Day) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, dayEnumStrings, dayEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Day. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Day) Ordinal() int {
37 | switch v {
38 | case Sunday:
39 | return 0
40 | case Monday:
41 | return 1
42 | case Tuesday:
43 | return 2
44 | case Wednesday:
45 | return 3
46 | case Thursday:
47 | return 4
48 | case Friday:
49 | return 5
50 | case Saturday:
51 | return 6
52 | }
53 | return -1
54 | }
55 |
56 | func (v Day) toString(o int, concats string, indexes []uint16) string {
57 | if o < 0 || o >= len(AllDays) {
58 | return fmt.Sprintf("Day(%d)", v)
59 | }
60 | return concats[indexes[o]:indexes[o+1]]
61 | }
62 |
63 | // IsValid determines whether a Day is one of the defined constants.
64 | func (v Day) IsValid() bool {
65 | return v.Ordinal() >= 0
66 | }
67 |
68 | // Int returns the int value, which is not necessarily the same as the ordinal.
69 | // This facilitates polymorphism (see enum.IntEnum).
70 | func (v Day) Int() int {
71 | return int(v)
72 | }
73 |
74 | var invalidDayValue = func() Day {
75 | var v Day
76 | for {
77 | if !slices.Contains(AllDays, v) {
78 | return v
79 | }
80 | v++
81 | } // AllDays is a finite set so loop will terminate eventually
82 | }()
83 |
84 | // DayOf returns a Day based on an ordinal number. This is the inverse of Ordinal.
85 | // If the ordinal is out of range, an invalid Day is returned.
86 | func DayOf(v int) Day {
87 | if 0 <= v && v < len(AllDays) {
88 | return AllDays[v]
89 | }
90 | return invalidDayValue
91 | }
92 |
93 | // Parse parses a string to find the corresponding Day, accepting one of the string values or
94 | // a number. It is used by AsDay.
95 | //
96 | // Usage Example
97 | //
98 | // v := new(Day)
99 | // err := v.Parse(s)
100 | // ... etc
101 | func (v *Day) Parse(in string) error {
102 | if v.parseNumber(in) {
103 | return nil
104 | }
105 |
106 | s := dayTransformInput(in)
107 |
108 | return v.parseFallback(in, s)
109 | }
110 |
111 | // parseNumber attempts to convert a decimal value.
112 | // Only numbers that correspond to the enumeration are valid.
113 | func (v *Day) parseNumber(s string) (ok bool) {
114 | num, err := strconv.ParseInt(s, 10, 64)
115 | if err == nil {
116 | *v = Day(num)
117 | return v.IsValid()
118 | }
119 | return false
120 | }
121 |
122 | func (v *Day) parseFallback(in, s string) error {
123 | if v.parseString(s, dayEnumStrings, dayEnumIndex[:]) {
124 | return nil
125 | }
126 |
127 | return errors.New(in + ": unrecognised day")
128 | }
129 |
130 | func (v *Day) parseString(s string, concats string, indexes []uint16) (ok bool) {
131 | var i0 uint16 = 0
132 |
133 | for j := 1; j < len(indexes); j++ {
134 | i1 := indexes[j]
135 | p := concats[i0:i1]
136 | if s == p {
137 | *v = AllDays[j-1]
138 | return true
139 | }
140 | i0 = i1
141 | }
142 | return false
143 | }
144 |
145 | // dayTransformInput may alter input strings before they are parsed.
146 | // This function is pluggable and is initialised using command-line flags
147 | // -ic -lc -uc -unsnake.
148 | var dayTransformInput = func(in string) string {
149 | return in
150 | }
151 |
152 | // AsDay parses a string to find the corresponding Day, accepting either one of the string values or
153 | // a number. It wraps Parse.
154 | func AsDay(s string) (Day, error) {
155 | var v = new(Day)
156 | err := v.Parse(s)
157 | return *v, err
158 | }
159 |
160 | // MustParseDay is similar to AsDay except that it panics on error.
161 | func MustParseDay(s string) Day {
162 | v, err := AsDay(s)
163 | if err != nil {
164 | panic(err)
165 | }
166 | return v
167 | }
168 |
--------------------------------------------------------------------------------
/example/example_test.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | import (
4 | "bytes"
5 | "encoding/gob"
6 | "encoding/json"
7 | "encoding/xml"
8 | "github.com/rickb777/expect"
9 | "testing"
10 | )
11 |
12 | func TestString(t *testing.T) {
13 | expect.String(Sunday.String()).ToBe(t, "Sunday")
14 | expect.String(Monday.String()).ToBe(t, "Monday")
15 | expect.String(MyDog.String()).ToBe(t, "dog")
16 | expect.String(OnlineSales.String()).ToBe(t, "online")
17 | }
18 |
19 | func TestOrdinal(t *testing.T) {
20 | expect.Number(int(Sunday)).ToBe(t, 1)
21 | expect.Number(Sunday.Ordinal()).ToBe(t, 0)
22 | expect.Number(int(Monday)).ToBe(t, 2)
23 | expect.Number(Monday.Ordinal()).ToBe(t, 1)
24 | expect.Number(Friday.Ordinal()).ToBe(t, 5)
25 | expect.Number(DayOf(0)).ToBe(t, Sunday)
26 | expect.Number(DayOf(3)).ToBe(t, Wednesday)
27 | expect.Number(DayOf(6)).ToBe(t, Saturday)
28 | expect.Number(DayOf(7)).ToBe(t, 0)
29 | expect.Number(DayOf(13)).ToBe(t, 0)
30 | expect.Bool(Wednesday.IsValid()).ToBeTrue(t)
31 | expect.Bool(Day(10).IsValid()).ToBeFalse(t)
32 | expect.Bool(DayOf(10).IsValid()).ToBeFalse(t)
33 | expect.Number(numberOfDays).ToBe(t, 7)
34 | }
35 |
36 | func TestIntOrFloat(t *testing.T) {
37 | expect.Number(G.Float()).ToBe(t, 347.20001220703125)
38 | expect.Number(Sunday.Int()).ToBe(t, 1)
39 | expect.Number(Wednesday.Int()).ToBe(t, 4)
40 | expect.Number(Θήτα.Int()).ToBe(t, 8)
41 | expect.Number(POST.Int()).ToBe(t, 3)
42 | expect.Number(November.Int()).ToBe(t, 11)
43 | expect.Number(MyKoala_Bear.Int()).ToBe(t, 4)
44 | }
45 |
46 | func TestAllDays(t *testing.T) {
47 | expect.Any(AllDays[0]).ToBe(t, Sunday)
48 | expect.Any(AllDays[5]).ToBe(t, Friday)
49 | }
50 |
51 | func TestAsDay(t *testing.T) {
52 | v, err := AsDay("Tuesday")
53 | expect.Any(v, err).ToBe(t, Tuesday)
54 | _, err = AsDay("Nosuchday")
55 | expect.Error(err).ToHaveOccurred(t)
56 | }
57 |
58 | func TestAsMethod(t *testing.T) {
59 | //methodMarshalTextRep = enum.Identifier
60 | expect.Number(AsMethod("POST")).ToBe(t, POST)
61 | //expect.Number(AsMethod("PO")).ToBe(POST))
62 | expect.Number(AsMethod("3")).ToBe(t, POST)
63 |
64 | expect.Number(AsMethod("PUT")).ToBe(t, PUT)
65 | //expect.Number( AsMethod("PU")).ToBe(PUT))
66 | expect.Number(AsMethod("2")).ToBe(t, PUT)
67 | }
68 |
69 | //-------------------------------------------------------------------------------------------------
70 |
71 | type Group struct {
72 | B Base
73 | D Day
74 | G GreekAlphabet
75 | X Method
76 | M Month
77 | P Pet
78 | C SalesChannel
79 | }
80 |
81 | func TestMarshal(t *testing.T) {
82 | //setMarshalReps(enum.Number)
83 | v := Group{G, Tuesday, Θήτα, POST, November, MyKoala_Bear, OnlineSales}
84 | s, err := json.Marshal(v)
85 | expect.Error(err).Not().ToHaveOccurred(t)
86 | x, err := xml.Marshal(v)
87 | expect.Error(err).Not().ToHaveOccurred(t)
88 | expect.String(s).ToEqual(t, `{"B":347.2,"D":3,"G":"theta","X":"PO","M":"November","P":"Phascolarctos Cinereus","C":"webshop"}`)
89 | expect.String(x).ToEqual(t, `347.23theta3NovemberPhascolarctos Cinereus
3`)
90 | }
91 |
92 | func TestMethodScan(t *testing.T) {
93 | //methodStoreRep = enum.Ordinal
94 | cases := []interface{}{
95 | int64(3), int64(3), float64(3), "POST", "post", []byte("POST"),
96 | }
97 | for i, s := range cases {
98 | if i > 0 {
99 | //methodStoreRep = enum.Identifier
100 | }
101 | var m = new(Method)
102 | err := m.Scan(s)
103 | expect.Error(err).Info(i).Not().ToHaveOccurred(t)
104 | expect.Number(*m).Info(i).ToBe(t, POST)
105 | }
106 | }
107 |
108 | //func TestMonthScan(t *testing.T) {
109 | // g := gomega.NewWithT(t)
110 | //
111 | // //monthStoreRep = enum.Ordinal
112 | // cases := []interface{}{
113 | // int64(10), int64(11), float64(11), "november", []byte("NOVEMBER"),
114 | // }
115 | // for i, s := range cases {
116 | // if i > 0 {
117 | // //monthStoreRep = enum.Identifier
118 | // }
119 | // var m = new(Month)
120 | // err := m.Scan(s)
121 | // expect.String(t, err).NotTo(gomega.HaveOccurred())
122 | // expect.String(t, *m).ToBe(November))
123 | // }
124 | //}
125 |
126 | //func TestPetScan(t *testing.T) {
127 | // g := gomega.NewWithT(t)
128 | //
129 | // //petStoreRep = enum.Ordinal
130 | // cases := []interface{}{
131 | // int64(4), int64(4), float64(4), "Koala Bear", "koala bear", "koala_bear", []byte("Koala Bear"), "Phascolarctos Cinereus",
132 | // }
133 | // for i, s := range cases {
134 | // if i > 0 {
135 | // //petStoreRep = enum.Identifier
136 | // }
137 | // var m = new(Pet)
138 | // err := m.Scan(s)
139 | // expect.String(t, err).NotTo(gomega.HaveOccurred())
140 | // expect.String(t, *m).ToBe(MyKoala_Bear))
141 | // }
142 | //}
143 |
144 | func TestSalesChannelScan(t *testing.T) {
145 | cases := []struct {
146 | in interface{}
147 | expected SalesChannel
148 | }{
149 | {in: int64(7), expected: TelephoneSales},
150 | {in: float64(7), expected: TelephoneSales},
151 | {in: "5", expected: InstoreSales},
152 | {in: "s", expected: InstoreSales},
153 | {in: []byte("o"), expected: OnlineSales},
154 | {in: nil, expected: 0},
155 | }
156 | for _, c := range cases {
157 | var m = new(SalesChannel)
158 | err := m.Scan(c.in)
159 | expect.Error(err).Info("%#v", c.in).ToBeNil(t)
160 | expect.Any(*m).Info("%#v", c.in).ToBe(t, c.expected)
161 | }
162 | }
163 |
164 | func TestValue(t *testing.T) {
165 | expect.Any(TelephoneSales.Value()).ToEqual(t, "t")
166 | expect.Any(Egypt.Value()).ToEqual(t, "eg")
167 | expect.Any(Ζήτα.Value()).ToEqual(t, "\u0396")
168 | expect.Any(POST.Value()).ToEqual(t, int64(3))
169 | }
170 |
171 | func TestGobEncodeAndDecode(t *testing.T) {
172 | v1 := Group{B: G, D: Tuesday, G: Θήτα, X: POST, M: November, P: MyKoala_Bear}
173 | gob.Register(v1)
174 |
175 | // gob-encode
176 | buf := &bytes.Buffer{}
177 | enc := gob.NewEncoder(buf)
178 | err := enc.Encode(v1)
179 | expect.Error(err).Not().ToHaveOccurred(t)
180 |
181 | // gob-decode
182 | var v2 Group
183 | dec := gob.NewDecoder(buf)
184 | err = dec.Decode(&v2)
185 | expect.Error(err).Not().ToHaveOccurred(t)
186 | expect.Any(v2).ToBe(t, v1)
187 | }
188 |
--------------------------------------------------------------------------------
/example/greekalphabet.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -type GreekAlphabet
4 |
5 | // GreekAlphabet example shows non-ASCII characters in use. There is also a cross-mapping
6 | // table specified via the '-using' option. So the parser recognises inputs from both
7 | // sets of strings.
8 | //
9 | // See also
10 | // https://unicode.org/charts/PDF/U0370.pdf
11 | // https://en.wikipedia.org/wiki/Greek_alphabet
12 | type GreekAlphabet int
13 |
14 | const (
15 | Αλφα GreekAlphabet = iota + 1 // text:"alpha" sql:"\u0391" = Α
16 | Βήτα // text:"beta" sql:"\u0392"
17 | Γάμμα // text:"gamma" sql:"\u0393"
18 | Δέλτα // text:"delta" sql:"\u0394"
19 | Εψιλον // text:"epsilon" sql:"\u0395"
20 | Ζήτα // text:"zeta" sql:"\u0396"
21 | Ητα // text:"eta" sql:"\u0397"
22 | Θήτα // text:"theta" sql:"\u0398"
23 | Ιώτα // text:"iota" sql:"\u0399"
24 | Κάππα // text:"kappa" sql:"\u039A"
25 | Λάμβδα // text:"lambda" sql:"\u039B"
26 | Μυ // text:"mu" sql:"\u039C"
27 | Νυ // text:"nu" sql:"\u039D"
28 | Ξι // text:"xi" sql:"\u039E"
29 | Ομικρον // text:"omicron" sql:"\u039F"
30 | Πι // text:"pi" sql:"\u03A0"
31 | Ρώ // text:"rho" sql:"\u03A1"
32 | Σίγμα // text:"sigma" sql:"\u03A3"
33 | Ταυ // text:"tau" sql:"\u03A4"
34 | Υψιλον // text:"upsilon" sql:"\u03A5"
35 | Φι // text:"phi" sql:"\u03A6"
36 | Χι // text:"chi" sql:"\u03A7"
37 | Ψι // text:"psi" sql:"\u03A8"
38 | Ωμέγα // text:"omega" sql:"\u03A9"
39 | // n.b. there is no u03A2
40 | )
41 |
--------------------------------------------------------------------------------
/example/method.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -type Method -ic -store number -poly
4 |
5 | // Method example has json tags that control the JSON representations. So the parser
6 | // recognises inputs from thes and the identifiers too. The '-ic' option means the parser ignores
7 | // the case of its inputs.
8 | //
9 | // See also SalesChannel.
10 | type Method uint
11 |
12 | const (
13 | HEAD Method = iota // json:"HE"
14 | GET // json:"GE"
15 | PUT // json:"PU"
16 | POST // json:"PO"
17 | PATCH // json:"PA"
18 | DELETE // json:"DE"
19 | )
20 |
--------------------------------------------------------------------------------
/example/month.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -type Month -ic -marshaltext identifier
4 |
5 | // Month example shows that several comma-separated enumeration constants can
6 | // be on each line, and they can have explicit values. The '-ic' option means
7 | // the parser ignores the case of its inputs.
8 | type Month uint
9 |
10 | const (
11 | January, February, March Month = 1, 2, 3
12 | April, May, June Month = 4, 5, 6
13 | July, August, September Month = 7, 8, 9
14 | October, November, December Month = 10, 11, 12
15 | )
16 |
--------------------------------------------------------------------------------
/example/pet.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | //go:generate enumeration -v -type Pet -prefix My -unsnake -lc -alias petAliases -lenient
4 |
5 | // Pet example has a cross-mapping table specified via the 'text' tags. So the parser
6 | // recognises inputs from both sets of strings. Also:
7 | //
8 | // - The '-lc' option means the parser expects lowercase inputs and the String method
9 | // gives lowercase values.
10 | //
11 | // - The -prefix option means each identifer, MyCat etc, is stored in the enumeration
12 | // as just "cat" without the "My" prefix.
13 | //
14 | // - Because of '-unsnake', underscores are replaced with spaces so "MyKoala_Bear" is
15 | // treated as "koala bear".
16 | //
17 | // - Because of the '-lenient' option, the parser will allow numbers outside the valid
18 | // range 0 to 4.
19 | type Pet uint16
20 |
21 | // These all have prefix "My", which is stripped from the String representation.
22 | const (
23 | MyCat Pet = iota // text:"Felis Catus"
24 | MyDog // text:"Canis Lupus"
25 | MyMouse // text:"Mus Musculus"
26 | MyElephant // text:"Loxodonta Africana"
27 | MyKoala_Bear // text:"Phascolarctos Cinereus"
28 | )
29 |
30 | // petAliases provide more strings that are recognised during parsing.
31 | // Although the map keys must be unique, the values do not need to be.
32 | // Note that -lc means the keys here mus also be lowercase.
33 | var petAliases = map[string]Pet{
34 | "sid": MyCat,
35 | "diego": MyCat,
36 | "pooch": MyDog,
37 | "whiskers": MyMouse,
38 | "faithful": MyElephant,
39 | "cuddly": MyKoala_Bear,
40 | }
41 |
--------------------------------------------------------------------------------
/example/pet_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package example
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllPets lists all 5 values in order.
15 | var AllPets = []Pet{
16 | MyCat, MyDog, MyMouse, MyElephant,
17 | MyKoala_Bear,
18 | }
19 |
20 | const (
21 | petEnumStrings = "catdogmouseelephantkoala bear"
22 | petTextStrings = "Felis CatusCanis LupusMus MusculusLoxodonta AfricanaPhascolarctos Cinereus"
23 | )
24 |
25 | var (
26 | petEnumIndex = [...]uint16{0, 3, 6, 11, 19, 29}
27 | petTextIndex = [...]uint16{0, 11, 22, 34, 52, 74}
28 | )
29 |
30 | // String returns the literal string representation of a Pet, which is
31 | // the same as the const identifier but without prefix or suffix.
32 | func (v Pet) String() string {
33 | o := v.Ordinal()
34 | return v.toString(o, petEnumStrings, petEnumIndex[:])
35 | }
36 |
37 | // Ordinal returns the ordinal number of a Pet. This is an integer counting
38 | // from zero. It is *not* the same as the const number assigned to the value.
39 | func (v Pet) Ordinal() int {
40 | switch v {
41 | case MyCat:
42 | return 0
43 | case MyDog:
44 | return 1
45 | case MyMouse:
46 | return 2
47 | case MyElephant:
48 | return 3
49 | case MyKoala_Bear:
50 | return 4
51 | }
52 | return -1
53 | }
54 |
55 | func (v Pet) toString(o int, concats string, indexes []uint16) string {
56 | if o < 0 || o >= len(AllPets) {
57 | return fmt.Sprintf("Pet(%d)", v)
58 | }
59 | return concats[indexes[o]:indexes[o+1]]
60 | }
61 |
62 | // IsValid determines whether a Pet is one of the defined constants.
63 | func (v Pet) IsValid() bool {
64 | return v.Ordinal() >= 0
65 | }
66 |
67 | // Int returns the int value, which is not necessarily the same as the ordinal.
68 | // This facilitates polymorphism (see enum.IntEnum).
69 | func (v Pet) Int() int {
70 | return int(v)
71 | }
72 |
73 | var invalidPetValue = func() Pet {
74 | var v Pet
75 | for {
76 | if !slices.Contains(AllPets, v) {
77 | return v
78 | }
79 | v++
80 | } // AllPets is a finite set so loop will terminate eventually
81 | }()
82 |
83 | // PetOf returns a Pet based on an ordinal number. This is the inverse of Ordinal.
84 | // If the ordinal is out of range, an invalid Pet is returned.
85 | func PetOf(v int) Pet {
86 | if 0 <= v && v < len(AllPets) {
87 | return AllPets[v]
88 | }
89 | return invalidPetValue
90 | }
91 |
92 | // Parse parses a string to find the corresponding Pet, accepting one of the string values or
93 | // a number. It is used by AsPet.
94 | //
95 | // Usage Example
96 | //
97 | // v := new(Pet)
98 | // err := v.Parse(s)
99 | // ... etc
100 | func (v *Pet) Parse(in string) error {
101 | if v.parseNumber(in) {
102 | return nil
103 | }
104 |
105 | s := petTransformInput(in)
106 |
107 | return v.parseFallback(in, s)
108 | }
109 |
110 | // parseNumber attempts to convert a decimal value.
111 | // Any number is allowed, even if the result is invalid.
112 | func (v *Pet) parseNumber(s string) (ok bool) {
113 | num, err := strconv.ParseInt(s, 10, 64)
114 | if err == nil {
115 | *v = Pet(num)
116 | return true
117 | }
118 | return false
119 | }
120 |
121 | func (v *Pet) parseFallback(in, s string) error {
122 | if v.parseString(s, petEnumStrings, petEnumIndex[:]) {
123 | return nil
124 | }
125 |
126 | var ok bool
127 | *v, ok = petAliases[s]
128 | if ok {
129 | return nil
130 | }
131 |
132 | return errors.New(in + ": unrecognised pet")
133 | }
134 |
135 | func (v *Pet) parseString(s string, concats string, indexes []uint16) (ok bool) {
136 | var i0 uint16 = 0
137 |
138 | for j := 1; j < len(indexes); j++ {
139 | i1 := indexes[j]
140 | p := concats[i0:i1]
141 | if s == p {
142 | *v = AllPets[j-1]
143 | return true
144 | }
145 | i0 = i1
146 | }
147 | *v, ok = petAliases[s]
148 | return ok
149 | }
150 |
151 | // petTransformInput may alter input strings before they are parsed.
152 | // This function is pluggable and is initialised using command-line flags
153 | // -ic -lc -uc -unsnake.
154 | var petTransformInput = func(in string) string {
155 | return strings.ReplaceAll(strings.ToLower(in), "_", " ")
156 | }
157 |
158 | // AsPet parses a string to find the corresponding Pet, accepting either one of the string values or
159 | // a number. It wraps Parse.
160 | func AsPet(s string) (Pet, error) {
161 | var v = new(Pet)
162 | err := v.Parse(s)
163 | return *v, err
164 | }
165 |
166 | // MustParsePet is similar to AsPet except that it panics on error.
167 | func MustParsePet(s string) Pet {
168 | v, err := AsPet(s)
169 | if err != nil {
170 | panic(err)
171 | }
172 | return v
173 | }
174 |
175 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
176 | func (v Pet) MarshalText() ([]byte, error) {
177 | s, err := v.marshalText()
178 | return []byte(s), err
179 | }
180 |
181 | // Text returns the representation used for transmission via XML, JSON etc.
182 | func (v Pet) Text() string {
183 | s, _ := v.marshalText()
184 | return s
185 | }
186 |
187 | // marshalText converts values to bytes suitable for transmission via XML, JSON etc.
188 | // The representation is chosen according to 'text' struct tags.
189 | func (v Pet) marshalText() (string, error) {
190 | o := v.Ordinal()
191 | if o < 0 {
192 | return v.marshalNumberStringOrError()
193 | }
194 |
195 | return v.toString(o, petTextStrings, petTextIndex[:]), nil
196 | }
197 |
198 | func (v Pet) marshalNumberStringOrError() (string, error) {
199 | bs, err := v.marshalNumberOrError()
200 | return string(bs), err
201 | }
202 |
203 | func (v Pet) marshalNumberOrError() ([]byte, error) {
204 | // allow lenient marshaling
205 | return []byte(petMarshalNumber(v)), nil
206 | }
207 |
208 | // petMarshalNumber handles marshaling where a number is required or where
209 | // the value is out of range.
210 | // This function can be replaced with any bespoke function than matches signature.
211 | var petMarshalNumber = func(v Pet) string {
212 | return strconv.FormatInt(int64(v), 10)
213 | }
214 |
215 | // UnmarshalText converts transmitted values to ordinary values.
216 | func (v *Pet) UnmarshalText(bs []byte) error {
217 | return v.unmarshalText(string(bs))
218 | }
219 |
220 | func (v *Pet) unmarshalText(in string) error {
221 | if v.parseNumber(in) {
222 | return nil
223 | }
224 |
225 | s := petTransformInput(in)
226 |
227 | if v.parseString(s, petTextStrings, petTextIndex[:]) {
228 | return nil
229 | }
230 |
231 | return v.parseFallback(in, s)
232 | }
233 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/rickb777/enumeration/v4
2 |
3 | require (
4 | github.com/magefile/mage v1.15.0
5 | github.com/rickb777/expect v0.24.0
6 | )
7 |
8 | require (
9 | github.com/google/go-cmp v0.7.0 // indirect
10 | github.com/rickb777/plural v1.4.4 // indirect
11 | )
12 |
13 | go 1.24.1
14 |
15 | tool github.com/magefile/mage
16 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
2 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
3 | github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
4 | github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
5 | github.com/rickb777/expect v0.21.0 h1:d06fVjsz2zGVfbEVRWetStwv/YKaxM4A0t39IzzST88=
6 | github.com/rickb777/expect v0.21.0/go.mod h1:NQTOf7atJ/89U2FLV1ghRp5XJDdZ8dV+8iW47kJ9q7c=
7 | github.com/rickb777/expect v0.24.0 h1:IzFxn4jINkVuCmx4jdQP7LxaIBhG60bDVbeGWk3xnzo=
8 | github.com/rickb777/expect v0.24.0/go.mod h1:jwwS3gmukQ7wPxzEtOhMJEv43UxSwOBE7MUgTt8CX0k=
9 | github.com/rickb777/plural v1.4.4 h1:OpZU8uRr9P2NkYAbkLMwlKNVJyJ5HvRcRBFyXGJtKGI=
10 | github.com/rickb777/plural v1.4.4/go.mod h1:DB19dtrplGS5s6VJVHn7tvmFYPoE83p1xqio3oVnNRM=
11 |
--------------------------------------------------------------------------------
/internal/codegen/units.go:
--------------------------------------------------------------------------------
1 | package codegen
2 |
3 | import (
4 | "github.com/rickb777/enumeration/v4/internal/collection"
5 | "slices"
6 | "unicode"
7 | )
8 |
9 | type Unit struct {
10 | Declares string
11 | Requires []string
12 | Extra map[string]any
13 | Imports collection.Set[string]
14 | Transforms bool
15 | Template string
16 | }
17 |
18 | func (u Unit) Exported() bool {
19 | d := u.Declares
20 | if d[:2] == "v." {
21 | d = d[2:]
22 | }
23 | return unicode.IsUpper(rune(d[0]))
24 | }
25 |
26 | type Units struct {
27 | m map[string]Unit
28 | l []string
29 | }
30 |
31 | func New() *Units {
32 | return &Units{m: make(map[string]Unit)}
33 | }
34 |
35 | func (units *Units) Add(unit Unit) *Units {
36 | _, exists := units.m[unit.Declares]
37 | if !exists {
38 | units.l = append(units.l, unit.Declares)
39 | units.m[unit.Declares] = unit
40 | }
41 | return units
42 | }
43 |
44 | func (units *Units) Take(identifier string) (u Unit, found bool) {
45 | units.l = slices.DeleteFunc(units.l, func(id string) bool {
46 | return id == identifier
47 | })
48 | u, found = units.m[identifier]
49 | //delete(units.m, identifier)
50 | return u, found
51 | }
52 |
53 | func (units *Units) Slice() []Unit {
54 | us := make([]Unit, 0, len(units.m))
55 | for _, id := range units.l {
56 | us = append(us, units.m[id])
57 | }
58 | return us
59 | }
60 |
--------------------------------------------------------------------------------
/internal/codegen/units_test.go:
--------------------------------------------------------------------------------
1 | package codegen
2 |
3 | import (
4 | "github.com/rickb777/enumeration/v4/internal/collection"
5 | "github.com/rickb777/expect"
6 | "testing"
7 | )
8 |
9 | func TestUnits(t *testing.T) {
10 | us1 := New()
11 | u1 := Unit{
12 | Declares: "aaa",
13 | Requires: []string{"bbb"},
14 | Extra: map[string]any{"eee": 1},
15 | Imports: collection.NewSet[string]("iii"),
16 | Template: "ttt",
17 | }
18 | us1.Add(u1)
19 | expect.Number(len(us1.m)).ToBe(t, 1)
20 | expect.Number(len(us1.l)).ToBe(t, 1)
21 |
22 | s := us1.Slice()
23 | expect.Number(len(s)).ToBe(t, 1)
24 | expect.Any(s).ToBe(t, []Unit{u1})
25 |
26 | q1, found := us1.Take("aaa")
27 | expect.Bool(found).ToBeTrue(t)
28 | expect.Any(q1).ToBe(t, u1)
29 | //Ω(len(us1.m)).ToBe(0,t)
30 | expect.Slice(us1.l).ToHaveLength(t, 0)
31 | }
32 |
--------------------------------------------------------------------------------
/internal/collection/set.go:
--------------------------------------------------------------------------------
1 | package collection
2 |
3 | import (
4 | "cmp"
5 | "slices"
6 | )
7 |
8 | type Set[T cmp.Ordered] map[T]struct{}
9 |
10 | func NewSet[T cmp.Ordered](vs ...T) Set[T] {
11 | return make(Set[T]).AddAll(vs...)
12 | }
13 |
14 | func (s Set[T]) AddAll(vs ...T) Set[T] {
15 | for _, v := range vs {
16 | s[v] = struct{}{}
17 | }
18 | return s
19 | }
20 |
21 | func (s Set[T]) Union(other Set[T]) Set[T] {
22 | for k := range other {
23 | s[k] = struct{}{}
24 | }
25 | return s
26 | }
27 |
28 | func (s Set[T]) Add(v T) {
29 | s[v] = struct{}{}
30 | }
31 |
32 | func (s Set[T]) Contains(v T) bool {
33 | _, exists := s[v]
34 | return exists
35 | }
36 |
37 | // Sorted returns the set as a sorted slice.
38 | func (s Set[T]) Sorted() []T {
39 | ss := make([]T, 0, len(s))
40 | for k := range s {
41 | ss = append(ss, k)
42 | }
43 | slices.Sort(ss)
44 | return ss
45 | }
46 |
--------------------------------------------------------------------------------
/internal/collection/set_test.go:
--------------------------------------------------------------------------------
1 | package collection
2 |
3 | import (
4 | "github.com/rickb777/expect"
5 | "testing"
6 | )
7 |
8 | func TestSetUnits(t *testing.T) {
9 | s1 := NewSet[string]("a", "b", "c")
10 | expect.Number(len(s1)).ToBe(t, 3)
11 | expect.Bool(s1.Contains("b")).ToBeTrue(t)
12 | expect.Bool(s1.Contains("x")).ToBeFalse(t)
13 |
14 | s1.AddAll("a", "x", "y")
15 | expect.Number(len(s1)).ToBe(t, 5)
16 | expect.Bool(s1.Contains("x")).ToBeTrue(t)
17 |
18 | s1.Add("z")
19 | expect.Number(len(s1)).ToBe(t, 6)
20 | expect.Bool(s1.Contains("z")).ToBeTrue(t)
21 |
22 | s1.Union(NewSet("a", "1", "b", "2"))
23 | expect.Number(len(s1)).ToBe(t, 8)
24 | expect.Bool(s1.Contains("2")).ToBeTrue(t)
25 |
26 | ss := s1.Sorted()
27 | expect.Slice(ss).ToBe(t, "1", "2", "a", "b", "c", "x", "y", "z")
28 | }
29 |
--------------------------------------------------------------------------------
/internal/parse/convert.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "fmt"
5 | "go/token"
6 | "go/types"
7 | "io"
8 | "regexp"
9 | "strings"
10 |
11 | "github.com/rickb777/enumeration/v4/internal/collection"
12 | "github.com/rickb777/enumeration/v4/internal/model"
13 | "github.com/rickb777/enumeration/v4/internal/transform"
14 | "github.com/rickb777/enumeration/v4/internal/util"
15 | )
16 |
17 | var (
18 | AliasTable string
19 | MainType string
20 | )
21 |
22 | var fset *token.FileSet
23 |
24 | var tagRE = regexp.MustCompile(`[a-z]:"`)
25 |
26 | // https://go.dev/doc/go1.17_spec#Type_declarations (without type parameters)
27 | // TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
28 | // TypeSpec = AliasDecl | TypeDef .
29 | //
30 | // TypeDef = identifier Type .
31 | //
32 | // Type = TypeName | TypeLit | "(" Type ")" .
33 | // TypeName = identifier | QualifiedIdent .
34 | // TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType .
35 |
36 | func Convert(in io.Reader, input string, xCase transform.Case, config model.Config) (model.Model, error) {
37 | src, err := io.ReadAll(in)
38 | if err != nil {
39 | return model.Model{}, err
40 | }
41 |
42 | MainType = config.MainType
43 |
44 | outTrans := transform.ListOf(xCase, transform.Unsnake(config.Unsnake))
45 | inTrans := outTrans
46 | if config.IgnoreCase && xCase == transform.Stet {
47 | inTrans = transform.ListOf(transform.Lower, transform.Unsnake(config.Unsnake))
48 | }
49 |
50 | m := model.Model{
51 | Config: config,
52 | LcType: strings.ToLower(config.MainType),
53 | BaseType: "int",
54 | InTrans: inTrans,
55 | OutTrans: outTrans,
56 | AliasTable: AliasTable,
57 | Extra: make(map[string]interface{}),
58 | Imports: collection.NewSet[string]("fmt"),
59 | }
60 |
61 | s := newFileScanner(input, src)
62 |
63 | var numFound = 0
64 | var constItems []constItem
65 | var baseType string
66 | var baseKind types.BasicKind
67 |
68 | for s.Scan() != token.EOF {
69 | switch s.Tok {
70 | case token.TYPE:
71 | baseType, baseKind, err = parseType(s, MainType, numFound)
72 | if err != nil {
73 | return m, fmt.Errorf("%s: %w", s.Position(), err)
74 | }
75 | if baseKind != types.Invalid {
76 | numFound++
77 | m.BaseType = baseType
78 | m.BaseKind = baseKind
79 | }
80 |
81 | case token.CONST:
82 | constItems = parseConst(s, constItems)
83 | }
84 | }
85 |
86 | debugConstItems(constItems)
87 |
88 | m.Values, _ = filterExportedItems(config.MainType, constItems)
89 |
90 | debugValues(m.Values)
91 |
92 | if s.gs.ErrorCount > 0 {
93 | return model.Model{}, fmt.Errorf("%s: syntax error\n%s", input, strings.Join(s.errs, "\n"))
94 | }
95 |
96 | if numFound == 0 {
97 | return model.Model{}, fmt.Errorf("%s: failed to find type %s", input, config.MainType)
98 | }
99 |
100 | if len(m.Values) == 0 {
101 | return model.Model{}, fmt.Errorf("%s: failed to find any values for %s", input, config.MainType)
102 | }
103 |
104 | if e2 := m.CheckBadPrefixSuffix(); e2 != nil {
105 | return model.Model{}, e2
106 | }
107 |
108 | if e2 := m.CheckBadTags(); e2 != nil {
109 | return model.Model{}, e2
110 | }
111 |
112 | return m, nil
113 | }
114 |
115 | func filterExportedItems(mainType string, ids []constItem) (exported model.Values, defaultValue string) {
116 | var currentType string
117 | exported = make(model.Values, 0, len(ids))
118 |
119 | for _, v := range ids {
120 | if v.typ == mainType {
121 | if token.IsExported(v.id) {
122 | exported = exported.Append(v.id, v.tag)
123 | switch v.expression {
124 | case "0", "iota":
125 | defaultValue = v.id
126 | }
127 | }
128 |
129 | } else if v.typ == "" && v.expression == "" && currentType == mainType {
130 | if token.IsExported(v.id) {
131 | exported = exported.Append(v.id, v.tag)
132 | }
133 | }
134 |
135 | if v.typ != "" {
136 | currentType = v.typ
137 | }
138 | }
139 |
140 | return exported, defaultValue
141 | }
142 |
143 | func debugConstItems(ids []constItem) {
144 | if util.Dbg {
145 | util.Debug("\n %-25s %-25s %-25s %s\n", "id", "type", "expression", "tag")
146 | for i, v := range ids {
147 | util.Debug("%-2d %-25s %-25s %-25s %s\n", i, v.id, v.typ, v.expression, v.tag)
148 | }
149 | }
150 | }
151 |
152 | func debugValues(values model.Values) {
153 | if util.Dbg {
154 | util.Debug("\n %-25s %-25s %-25s %s\n", "id", "short", "json", "sql")
155 | for i, v := range values {
156 | util.Debug("%-2d %-25s %-25s %-25s %s\n", i, v.Identifier, v.Shortened, v.JSON, v.SQL)
157 | }
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/internal/parse/parse_const.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "github.com/rickb777/enumeration/v4/internal/util"
5 | "go/token"
6 | "reflect"
7 | "strings"
8 | )
9 |
10 | type constItem struct {
11 | id, typ, expression string
12 | tag reflect.StructTag
13 | }
14 |
15 | func appendConstItems(items []constItem, ids []string, typ string, number string, tag reflect.StructTag) []constItem {
16 | if len(ids) == 1 {
17 | // include the tag
18 | return append(items, constItem{id: ids[0], typ: typ, expression: number, tag: tag})
19 | }
20 |
21 | // don't include the tag
22 | for _, id := range ids {
23 | items = append(items, constItem{id: id, typ: typ, expression: number})
24 | }
25 | return items
26 | }
27 |
28 | //-------------------------------------------------------------------------------------------------
29 | // https://go.dev/doc/go1.17_spec#Constant_declarations
30 | // ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
31 | // ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
32 | //
33 | // IdentifierList = identifier { "," identifier } .
34 | // ExpressionList = Expression { "," Expression } .
35 |
36 | func parseConst(s *scanner, items []constItem) []constItem {
37 | for s.Tok != token.EOF {
38 | switch s.Scan() {
39 | case token.IDENT:
40 | return parseConstSpec(s, items)
41 |
42 | case token.LPAREN:
43 | return parseConstBlock(s, items)
44 | }
45 | }
46 | return items
47 | }
48 |
49 | func parseConstSpec(s *scanner, items []constItem) []constItem {
50 | ids := parseStringList(s)
51 |
52 | // parse the Type and the ExpressionList
53 | for s.Scan() != token.EOF {
54 | switch s.Tok {
55 | case token.IDENT:
56 | typeName := s.Lit
57 | switch s.Scan() {
58 | case token.ASSIGN:
59 | restOfLine, tag := readToEndOfLine(s)
60 | return appendConstItems(items, ids, typeName, restOfLine, tag)
61 | }
62 |
63 | case token.ASSIGN:
64 | restOfLine, tag := readToEndOfLine(s)
65 | return appendConstItems(items, ids, "", restOfLine, tag)
66 | }
67 | }
68 |
69 | return items
70 | }
71 |
72 | func parseStringList(s *scanner) []string {
73 | var ids []string
74 | for s.Tok == token.IDENT {
75 | ids = append(ids, s.Lit)
76 |
77 | if s.Peek() != token.COMMA {
78 | return ids
79 | }
80 |
81 | s.Scan() // the comma
82 | s.Scan() // the next ident?
83 | }
84 |
85 | return ids
86 | }
87 |
88 | func parseConstBlock(s *scanner, items []constItem) []constItem {
89 | for s.Scan() != token.EOF {
90 | switch s.Tok {
91 | case token.IDENT:
92 | ids := parseStringList(s)
93 |
94 | switch s.Scan() {
95 | case token.IDENT:
96 | typeName := s.Lit
97 | if s.Scan() == token.ASSIGN {
98 | restOfLine, tag := readToEndOfLine(s)
99 | items = appendConstItems(items, ids, typeName, restOfLine, tag)
100 | ids = nil
101 | } else {
102 | readToEndOfLine(s) // discard likely compilation error
103 | }
104 |
105 | case token.COMMENT:
106 | _, tag := readToEndOfLine(s)
107 | items = appendConstItems(items, ids, "", "", tag)
108 | ids = nil
109 |
110 | case token.SEMICOLON:
111 | restOfLine, tag := readToEndOfLine(s)
112 | items = appendConstItems(items, ids, "", restOfLine, tag)
113 | ids = nil
114 | }
115 |
116 | case token.RPAREN, token.EOF:
117 | return items
118 |
119 | //default:
120 | // _, _ = readToEndOfLine(s)
121 | }
122 | }
123 |
124 | return items
125 | }
126 |
127 | func readToEndOfLine(s *scanner) (rest string, commentTag reflect.StructTag) {
128 | if s.Tok == token.ASSIGN {
129 | s.Scan()
130 | }
131 |
132 | for s.Tok != token.SEMICOLON && s.Tok != token.EOF {
133 | if rest != "" {
134 | rest += " "
135 | }
136 | if s.Lit != "" {
137 | rest += s.Lit
138 | } else {
139 | rest += s.Tok.String()
140 | }
141 |
142 | if s.Tok == token.COMMENT {
143 | comment := strings.TrimSpace(s.Lit)
144 | if strings.HasPrefix(comment, "//") {
145 | comment = strings.TrimSpace(comment[2:])
146 | if tagRE.MatchString(comment) {
147 | commentTag = reflect.StructTag(comment)
148 | }
149 |
150 | // COMMENT is optionally followed by SEMICOLON/EOF
151 | // but if not, then we've reached the end of the line anyway
152 | if s.nextTok != token.SEMICOLON && s.nextTok != token.EOF {
153 | util.Debug("%s ----- comment return %q %s\n", fset.Position(s.Pos), rest, commentTag)
154 | return rest, commentTag
155 | }
156 | }
157 | }
158 |
159 | s.Scan()
160 | }
161 |
162 | util.Debug("%s ----- return %q %s\n", fset.Position(s.Pos), rest, commentTag)
163 | return rest, commentTag
164 | }
165 |
--------------------------------------------------------------------------------
/internal/parse/parse_type.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "fmt"
5 | "go/token"
6 | "go/types"
7 | "math"
8 | )
9 |
10 | func parseType(s *scanner, mainType string, numFound int) (string, types.BasicKind, error) {
11 | for s.Tok != token.EOF {
12 | switch s.Scan() {
13 | case token.IDENT:
14 | return parseTypeSpec(s, mainType, numFound, 1)
15 |
16 | case token.LPAREN:
17 | switch s.Scan() {
18 | case token.IDENT:
19 | return parseTypeSpec(s, mainType, numFound, math.MaxInt)
20 | }
21 | }
22 | }
23 |
24 | return "", 0, nil
25 | }
26 |
27 | func parseTypeSpec(s *scanner, mainType string, numFound int, inBlock int) (string, types.BasicKind, error) {
28 | for s.Tok != token.EOF && inBlock > 0 {
29 | if s.Tok == token.IDENT && s.Lit == mainType {
30 | if numFound > 0 {
31 | return "", types.Invalid, fmt.Errorf("found multiple type %s declarations", mainType)
32 | }
33 | switch s.Scan() {
34 | case token.IDENT:
35 | switch s.Lit {
36 | case "int", "uint",
37 | "int8", "uint8",
38 | "int16", "uint16",
39 | "int32", "uint32",
40 | "int64", "uint64",
41 | "byte", "rune":
42 | return s.Lit, types.Int, nil
43 | case "float32", "float64":
44 | return s.Lit, types.Float64, nil
45 | default:
46 | return "", types.Invalid, fmt.Errorf("enumeration type %s must be an integer or float type", mainType)
47 | }
48 |
49 | case token.ASSIGN:
50 | return "", types.Invalid, fmt.Errorf("type %s is a type alias (not supported)", mainType)
51 |
52 | default:
53 | return "", types.Invalid, fmt.Errorf("syntax error in type %s declaration", mainType)
54 | }
55 | }
56 | s.Scan()
57 | inBlock--
58 | }
59 |
60 | return "", 0, nil
61 | }
62 |
--------------------------------------------------------------------------------
/internal/parse/scanner.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "fmt"
5 | "github.com/rickb777/enumeration/v4/internal/util"
6 | goscanner "go/scanner"
7 | "go/token"
8 | )
9 |
10 | // scanner implements a one-place lookahead wrapper around the Go scanner.
11 | // It also coalesces SEMICOLON and COMMENT into one apparent SEMICOLON
12 | // with the literal from the COMMENT.
13 | type scanner struct {
14 | gs *goscanner.Scanner
15 | errs []string
16 | Pos token.Pos
17 | Tok token.Token
18 | Lit string
19 | nextPos token.Pos
20 | nextTok token.Token
21 | nextLit string
22 | }
23 |
24 | func (s *scanner) Peek() token.Token {
25 | return s.nextTok
26 | }
27 |
28 | func (s *scanner) doScan() {
29 | s.nextPos, s.nextTok, s.nextLit = s.gs.Scan()
30 | s.debug()
31 | }
32 |
33 | func (s *scanner) debug() {
34 | if s.Lit == "" {
35 | util.Debug("%-18s %s\n", fset.Position(s.Pos), s.Tok)
36 | } else {
37 | util.Debug("%-18s %-8s %q\n", fset.Position(s.Pos), s.Tok, s.Lit)
38 | }
39 | }
40 |
41 | func (s *scanner) Position() token.Position {
42 | return fset.Position(s.Pos)
43 | }
44 |
45 | func (s *scanner) Scan() token.Token {
46 | switch s.Tok {
47 | case token.EOF:
48 | return token.EOF
49 | }
50 |
51 | s.Pos = s.nextPos
52 | s.Tok = s.nextTok
53 | s.Lit = s.nextLit
54 |
55 | s.doScan()
56 |
57 | return s.Tok
58 | }
59 |
60 | func newFileScanner(input string, src []byte) *scanner {
61 | gs := new(goscanner.Scanner)
62 | sc := &scanner{gs: gs}
63 | eh := func(pos token.Position, msg string) {
64 | sc.errs = append(sc.errs, fmt.Sprintf("%s: %s", pos, msg))
65 | }
66 |
67 | fset = token.NewFileSet() // positions are relative to fset
68 | file := fset.AddFile(input, fset.Base(), len(src)) // register input "file"
69 | gs.Init(file, src, eh, goscanner.ScanComments)
70 | return sc
71 | }
72 |
--------------------------------------------------------------------------------
/internal/test/combinations.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rickb777/enumeration/eb21a46ef340fe393a3d41a02cffedb45348ef92/internal/test/combinations.xlsx
--------------------------------------------------------------------------------
/internal/test/season.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | //go:generate enumeration -v -f -i season.go -type Season1 -suffix 1
4 |
5 | type Season1 uint
6 |
7 | const (
8 | _ Season1 = iota
9 | Spring1
10 | Summer1
11 | Autumn1
12 | Winter1
13 | )
14 |
15 | //-------------------------------------------------------------------------------------------------
16 | //go:generate enumeration -v -f -i season.go -type Season2 -suffix 2 -alias season2Alias
17 |
18 | type Season2 uint
19 |
20 | const (
21 | _ Season2 = iota
22 | Spring2
23 | Summer2
24 | Autumn2
25 | Winter2
26 | )
27 |
28 | var season2Alias = map[string]Season2{
29 | "Fall2": Autumn2,
30 | }
31 |
--------------------------------------------------------------------------------
/internal/test/season1_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllSeason1s lists all 4 values in order.
14 | var AllSeason1s = []Season1{
15 | Spring1, Summer1, Autumn1, Winter1,
16 | }
17 |
18 | const (
19 | season1EnumStrings = "SpringSummerAutumnWinter"
20 | )
21 |
22 | var (
23 | season1EnumIndex = [...]uint16{0, 6, 12, 18, 24}
24 | )
25 |
26 | // String returns the literal string representation of a Season1, which is
27 | // the same as the const identifier but without prefix or suffix.
28 | func (v Season1) String() string {
29 | o := v.Ordinal()
30 | return v.toString(o, season1EnumStrings, season1EnumIndex[:])
31 | }
32 |
33 | // Ordinal returns the ordinal number of a Season1. This is an integer counting
34 | // from zero. It is *not* the same as the const number assigned to the value.
35 | func (v Season1) Ordinal() int {
36 | switch v {
37 | case Spring1:
38 | return 0
39 | case Summer1:
40 | return 1
41 | case Autumn1:
42 | return 2
43 | case Winter1:
44 | return 3
45 | }
46 | return -1
47 | }
48 |
49 | func (v Season1) toString(o int, concats string, indexes []uint16) string {
50 | if o < 0 || o >= len(AllSeason1s) {
51 | return fmt.Sprintf("Season1(%d)", v)
52 | }
53 | return concats[indexes[o]:indexes[o+1]]
54 | }
55 |
56 | // IsValid determines whether a Season1 is one of the defined constants.
57 | func (v Season1) IsValid() bool {
58 | return v.Ordinal() >= 0
59 | }
60 |
61 | // Int returns the int value, which is not necessarily the same as the ordinal.
62 | // This facilitates polymorphism (see enum.IntEnum).
63 | func (v Season1) Int() int {
64 | return int(v)
65 | }
66 |
67 | var invalidSeason1Value = func() Season1 {
68 | var v Season1
69 | for {
70 | if !slices.Contains(AllSeason1s, v) {
71 | return v
72 | }
73 | v++
74 | } // AllSeason1s is a finite set so loop will terminate eventually
75 | }()
76 |
77 | // Season1Of returns a Season1 based on an ordinal number. This is the inverse of Ordinal.
78 | // If the ordinal is out of range, an invalid Season1 is returned.
79 | func Season1Of(v int) Season1 {
80 | if 0 <= v && v < len(AllSeason1s) {
81 | return AllSeason1s[v]
82 | }
83 | return invalidSeason1Value
84 | }
85 |
86 | // Parse parses a string to find the corresponding Season1, accepting one of the string values or
87 | // a number. It is used by AsSeason1.
88 | //
89 | // Usage Example
90 | //
91 | // v := new(Season1)
92 | // err := v.Parse(s)
93 | // ... etc
94 | func (v *Season1) Parse(in string) error {
95 | if v.parseNumber(in) {
96 | return nil
97 | }
98 |
99 | s := season1TransformInput(in)
100 |
101 | return v.parseFallback(in, s)
102 | }
103 |
104 | // parseNumber attempts to convert a decimal value.
105 | // Only numbers that correspond to the enumeration are valid.
106 | func (v *Season1) parseNumber(s string) (ok bool) {
107 | num, err := strconv.ParseInt(s, 10, 64)
108 | if err == nil {
109 | *v = Season1(num)
110 | return v.IsValid()
111 | }
112 | return false
113 | }
114 |
115 | func (v *Season1) parseFallback(in, s string) error {
116 | if v.parseString(s, season1EnumStrings, season1EnumIndex[:]) {
117 | return nil
118 | }
119 |
120 | return errors.New(in + ": unrecognised season1")
121 | }
122 |
123 | func (v *Season1) parseString(s string, concats string, indexes []uint16) (ok bool) {
124 | var i0 uint16 = 0
125 |
126 | for j := 1; j < len(indexes); j++ {
127 | i1 := indexes[j]
128 | p := concats[i0:i1]
129 | if s == p {
130 | *v = AllSeason1s[j-1]
131 | return true
132 | }
133 | i0 = i1
134 | }
135 | return false
136 | }
137 |
138 | // season1TransformInput may alter input strings before they are parsed.
139 | // This function is pluggable and is initialised using command-line flags
140 | // -ic -lc -uc -unsnake.
141 | var season1TransformInput = func(in string) string {
142 | return in
143 | }
144 |
145 | // AsSeason1 parses a string to find the corresponding Season1, accepting either one of the string values or
146 | // a number. It wraps Parse.
147 | func AsSeason1(s string) (Season1, error) {
148 | var v = new(Season1)
149 | err := v.Parse(s)
150 | return *v, err
151 | }
152 |
153 | // MustParseSeason1 is similar to AsSeason1 except that it panics on error.
154 | func MustParseSeason1(s string) Season1 {
155 | v, err := AsSeason1(s)
156 | if err != nil {
157 | panic(err)
158 | }
159 | return v
160 | }
161 |
--------------------------------------------------------------------------------
/internal/test/season2_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllSeason2s lists all 4 values in order.
14 | var AllSeason2s = []Season2{
15 | Spring2, Summer2, Autumn2, Winter2,
16 | }
17 |
18 | const (
19 | season2EnumStrings = "SpringSummerAutumnWinter"
20 | )
21 |
22 | var (
23 | season2EnumIndex = [...]uint16{0, 6, 12, 18, 24}
24 | )
25 |
26 | // String returns the literal string representation of a Season2, which is
27 | // the same as the const identifier but without prefix or suffix.
28 | func (v Season2) String() string {
29 | o := v.Ordinal()
30 | return v.toString(o, season2EnumStrings, season2EnumIndex[:])
31 | }
32 |
33 | // Ordinal returns the ordinal number of a Season2. This is an integer counting
34 | // from zero. It is *not* the same as the const number assigned to the value.
35 | func (v Season2) Ordinal() int {
36 | switch v {
37 | case Spring2:
38 | return 0
39 | case Summer2:
40 | return 1
41 | case Autumn2:
42 | return 2
43 | case Winter2:
44 | return 3
45 | }
46 | return -1
47 | }
48 |
49 | func (v Season2) toString(o int, concats string, indexes []uint16) string {
50 | if o < 0 || o >= len(AllSeason2s) {
51 | return fmt.Sprintf("Season2(%d)", v)
52 | }
53 | return concats[indexes[o]:indexes[o+1]]
54 | }
55 |
56 | // IsValid determines whether a Season2 is one of the defined constants.
57 | func (v Season2) IsValid() bool {
58 | return v.Ordinal() >= 0
59 | }
60 |
61 | // Int returns the int value, which is not necessarily the same as the ordinal.
62 | // This facilitates polymorphism (see enum.IntEnum).
63 | func (v Season2) Int() int {
64 | return int(v)
65 | }
66 |
67 | var invalidSeason2Value = func() Season2 {
68 | var v Season2
69 | for {
70 | if !slices.Contains(AllSeason2s, v) {
71 | return v
72 | }
73 | v++
74 | } // AllSeason2s is a finite set so loop will terminate eventually
75 | }()
76 |
77 | // Season2Of returns a Season2 based on an ordinal number. This is the inverse of Ordinal.
78 | // If the ordinal is out of range, an invalid Season2 is returned.
79 | func Season2Of(v int) Season2 {
80 | if 0 <= v && v < len(AllSeason2s) {
81 | return AllSeason2s[v]
82 | }
83 | return invalidSeason2Value
84 | }
85 |
86 | // Parse parses a string to find the corresponding Season2, accepting one of the string values or
87 | // a number. It is used by AsSeason2.
88 | //
89 | // Usage Example
90 | //
91 | // v := new(Season2)
92 | // err := v.Parse(s)
93 | // ... etc
94 | func (v *Season2) Parse(in string) error {
95 | if v.parseNumber(in) {
96 | return nil
97 | }
98 |
99 | s := season2TransformInput(in)
100 |
101 | return v.parseFallback(in, s)
102 | }
103 |
104 | // parseNumber attempts to convert a decimal value.
105 | // Only numbers that correspond to the enumeration are valid.
106 | func (v *Season2) parseNumber(s string) (ok bool) {
107 | num, err := strconv.ParseInt(s, 10, 64)
108 | if err == nil {
109 | *v = Season2(num)
110 | return v.IsValid()
111 | }
112 | return false
113 | }
114 |
115 | func (v *Season2) parseFallback(in, s string) error {
116 | if v.parseString(s, season2EnumStrings, season2EnumIndex[:]) {
117 | return nil
118 | }
119 |
120 | var ok bool
121 | *v, ok = season2Alias[s]
122 | if ok {
123 | return nil
124 | }
125 |
126 | return errors.New(in + ": unrecognised season2")
127 | }
128 |
129 | func (v *Season2) parseString(s string, concats string, indexes []uint16) (ok bool) {
130 | var i0 uint16 = 0
131 |
132 | for j := 1; j < len(indexes); j++ {
133 | i1 := indexes[j]
134 | p := concats[i0:i1]
135 | if s == p {
136 | *v = AllSeason2s[j-1]
137 | return true
138 | }
139 | i0 = i1
140 | }
141 | *v, ok = season2Alias[s]
142 | return ok
143 | }
144 |
145 | // season2TransformInput may alter input strings before they are parsed.
146 | // This function is pluggable and is initialised using command-line flags
147 | // -ic -lc -uc -unsnake.
148 | var season2TransformInput = func(in string) string {
149 | return in
150 | }
151 |
152 | // AsSeason2 parses a string to find the corresponding Season2, accepting either one of the string values or
153 | // a number. It wraps Parse.
154 | func AsSeason2(s string) (Season2, error) {
155 | var v = new(Season2)
156 | err := v.Parse(s)
157 | return *v, err
158 | }
159 |
160 | // MustParseSeason2 is similar to AsSeason2 except that it panics on error.
161 | func MustParseSeason2(s string) Season2 {
162 | v, err := AsSeason2(s)
163 | if err != nil {
164 | panic(err)
165 | }
166 | return v
167 | }
168 |
--------------------------------------------------------------------------------
/internal/test/season_ic_jn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Ic_Jns lists all 4 values in order.
15 | var AllSeason_Ic_Jns = []Season_Ic_Jn{
16 | Spring_Ic_Jn, Summer_Ic_Jn, Autumn_Ic_Jn, Winter_Ic_Jn,
17 | }
18 |
19 | const (
20 | season_ic_jnEnumStrings = "SpringSummerAutumnWinter"
21 | season_ic_jnEnumInputs = "springsummerautumnwinter"
22 | )
23 |
24 | var (
25 | season_ic_jnEnumIndex = [...]uint16{0, 6, 12, 18, 24}
26 | )
27 |
28 | // String returns the literal string representation of a Season_Ic_Jn, which is
29 | // the same as the const identifier but without prefix or suffix.
30 | func (v Season_Ic_Jn) String() string {
31 | o := v.Ordinal()
32 | return v.toString(o, season_ic_jnEnumStrings, season_ic_jnEnumIndex[:])
33 | }
34 |
35 | // Ordinal returns the ordinal number of a Season_Ic_Jn. This is an integer counting
36 | // from zero. It is *not* the same as the const number assigned to the value.
37 | func (v Season_Ic_Jn) Ordinal() int {
38 | switch v {
39 | case Spring_Ic_Jn:
40 | return 0
41 | case Summer_Ic_Jn:
42 | return 1
43 | case Autumn_Ic_Jn:
44 | return 2
45 | case Winter_Ic_Jn:
46 | return 3
47 | }
48 | return -1
49 | }
50 |
51 | func (v Season_Ic_Jn) toString(o int, concats string, indexes []uint16) string {
52 | if o < 0 || o >= len(AllSeason_Ic_Jns) {
53 | return fmt.Sprintf("Season_Ic_Jn(%d)", v)
54 | }
55 | return concats[indexes[o]:indexes[o+1]]
56 | }
57 |
58 | // IsValid determines whether a Season_Ic_Jn is one of the defined constants.
59 | func (v Season_Ic_Jn) IsValid() bool {
60 | return v.Ordinal() >= 0
61 | }
62 |
63 | // Int returns the int value, which is not necessarily the same as the ordinal.
64 | // This facilitates polymorphism (see enum.IntEnum).
65 | func (v Season_Ic_Jn) Int() int {
66 | return int(v)
67 | }
68 |
69 | var invalidSeason_Ic_JnValue = func() Season_Ic_Jn {
70 | var v Season_Ic_Jn
71 | for {
72 | if !slices.Contains(AllSeason_Ic_Jns, v) {
73 | return v
74 | }
75 | v++
76 | } // AllSeason_Ic_Jns is a finite set so loop will terminate eventually
77 | }()
78 |
79 | // Season_Ic_JnOf returns a Season_Ic_Jn based on an ordinal number. This is the inverse of Ordinal.
80 | // If the ordinal is out of range, an invalid Season_Ic_Jn is returned.
81 | func Season_Ic_JnOf(v int) Season_Ic_Jn {
82 | if 0 <= v && v < len(AllSeason_Ic_Jns) {
83 | return AllSeason_Ic_Jns[v]
84 | }
85 | return invalidSeason_Ic_JnValue
86 | }
87 |
88 | // Parse parses a string to find the corresponding Season_Ic_Jn, accepting one of the string values or
89 | // a number. It is used by AsSeason_Ic_Jn.
90 | // The input case does not matter.
91 | //
92 | // Usage Example
93 | //
94 | // v := new(Season_Ic_Jn)
95 | // err := v.Parse(s)
96 | // ... etc
97 | func (v *Season_Ic_Jn) Parse(in string) error {
98 | if v.parseNumber(in) {
99 | return nil
100 | }
101 |
102 | s := season_ic_jnTransformInput(in)
103 |
104 | return v.parseFallback(in, s)
105 | }
106 |
107 | // parseNumber attempts to convert a decimal value.
108 | // Only numbers that correspond to the enumeration are valid.
109 | func (v *Season_Ic_Jn) parseNumber(s string) (ok bool) {
110 | num, err := strconv.ParseInt(s, 10, 64)
111 | if err == nil {
112 | *v = Season_Ic_Jn(num)
113 | return v.IsValid()
114 | }
115 | return false
116 | }
117 |
118 | func (v *Season_Ic_Jn) parseFallback(in, s string) error {
119 | if v.parseString(s, season_ic_jnEnumInputs, season_ic_jnEnumIndex[:]) {
120 | return nil
121 | }
122 |
123 | return errors.New(in + ": unrecognised season_ic_jn")
124 | }
125 |
126 | func (v *Season_Ic_Jn) parseString(s string, concats string, indexes []uint16) (ok bool) {
127 | var i0 uint16 = 0
128 |
129 | for j := 1; j < len(indexes); j++ {
130 | i1 := indexes[j]
131 | p := concats[i0:i1]
132 | if s == p {
133 | *v = AllSeason_Ic_Jns[j-1]
134 | return true
135 | }
136 | i0 = i1
137 | }
138 | return false
139 | }
140 |
141 | // season_ic_jnTransformInput may alter input strings before they are parsed.
142 | // This function is pluggable and is initialised using command-line flags
143 | // -ic -lc -uc -unsnake.
144 | var season_ic_jnTransformInput = func(in string) string {
145 | return strings.ToLower(in)
146 | }
147 |
148 | // AsSeason_Ic_Jn parses a string to find the corresponding Season_Ic_Jn, accepting either one of the string values or
149 | // a number. It wraps Parse.
150 | // The input case does not matter.
151 | func AsSeason_Ic_Jn(s string) (Season_Ic_Jn, error) {
152 | var v = new(Season_Ic_Jn)
153 | err := v.Parse(s)
154 | return *v, err
155 | }
156 |
157 | // MustParseSeason_Ic_Jn is similar to AsSeason_Ic_Jn except that it panics on error.
158 | // The input case does not matter.
159 | func MustParseSeason_Ic_Jn(s string) Season_Ic_Jn {
160 | v, err := AsSeason_Ic_Jn(s)
161 | if err != nil {
162 | panic(err)
163 | }
164 | return v
165 | }
166 |
167 | // MarshalJSON converts values to bytes suitable for transmission via JSON.
168 | // The number representation is chosen according to -marshaljson.
169 | func (v Season_Ic_Jn) MarshalJSON() ([]byte, error) {
170 | if !v.IsValid() {
171 | return v.marshalNumberOrError()
172 | }
173 |
174 | s := season_ic_jnMarshalNumber(v)
175 | return []byte(s), nil
176 | }
177 |
178 | func (v Season_Ic_Jn) marshalNumberOrError() ([]byte, error) {
179 | // disallow lenient marshaling
180 | return nil, v.invalidError()
181 | }
182 |
183 | func (v Season_Ic_Jn) invalidError() error {
184 | return fmt.Errorf("%d is not a valid season_ic_jn", v)
185 | }
186 |
187 | // season_ic_jnMarshalNumber handles marshaling where a number is required or where
188 | // the value is out of range.
189 | // This function can be replaced with any bespoke function than matches signature.
190 | var season_ic_jnMarshalNumber = func(v Season_Ic_Jn) string {
191 | return strconv.FormatInt(int64(v), 10)
192 | }
193 |
194 | // UnmarshalJSON converts transmitted JSON values to ordinary values. It allows both
195 | // ordinals and strings to represent the values.
196 | func (v *Season_Ic_Jn) UnmarshalJSON(text []byte) error {
197 | s := string(text)
198 | if s == "null" {
199 | // Ignore null, like in the main JSON package.
200 | return nil
201 | }
202 | s = strings.Trim(s, "\"")
203 | return v.unmarshalJSON(s)
204 | }
205 |
206 | func (v *Season_Ic_Jn) unmarshalJSON(in string) error {
207 | if v.parseNumber(in) {
208 | return nil
209 | }
210 |
211 | s := season_ic_jnTransformInput(in)
212 |
213 | if v.parseString(s, season_ic_jnEnumInputs, season_ic_jnEnumIndex[:]) {
214 | return nil
215 | }
216 |
217 | return errors.New(in + ": unrecognised season_ic_jn")
218 | }
219 |
--------------------------------------------------------------------------------
/internal/test/season_ic_si_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | // AllSeason_Ic_Sis lists all 4 values in order.
16 | var AllSeason_Ic_Sis = []Season_Ic_Si{
17 | Spring_Ic_Si, Summer_Ic_Si, Autumn_Ic_Si, Winter_Ic_Si,
18 | }
19 |
20 | const (
21 | season_ic_siEnumStrings = "SpringSummerAutumnWinter"
22 | season_ic_siEnumInputs = "springsummerautumnwinter"
23 | )
24 |
25 | var (
26 | season_ic_siEnumIndex = [...]uint16{0, 6, 12, 18, 24}
27 | )
28 |
29 | // String returns the literal string representation of a Season_Ic_Si, which is
30 | // the same as the const identifier but without prefix or suffix.
31 | func (v Season_Ic_Si) String() string {
32 | o := v.Ordinal()
33 | return v.toString(o, season_ic_siEnumStrings, season_ic_siEnumIndex[:])
34 | }
35 |
36 | // Ordinal returns the ordinal number of a Season_Ic_Si. This is an integer counting
37 | // from zero. It is *not* the same as the const number assigned to the value.
38 | func (v Season_Ic_Si) Ordinal() int {
39 | switch v {
40 | case Spring_Ic_Si:
41 | return 0
42 | case Summer_Ic_Si:
43 | return 1
44 | case Autumn_Ic_Si:
45 | return 2
46 | case Winter_Ic_Si:
47 | return 3
48 | }
49 | return -1
50 | }
51 |
52 | func (v Season_Ic_Si) toString(o int, concats string, indexes []uint16) string {
53 | if o < 0 || o >= len(AllSeason_Ic_Sis) {
54 | return fmt.Sprintf("Season_Ic_Si(%d)", v)
55 | }
56 | return concats[indexes[o]:indexes[o+1]]
57 | }
58 |
59 | // IsValid determines whether a Season_Ic_Si is one of the defined constants.
60 | func (v Season_Ic_Si) IsValid() bool {
61 | return v.Ordinal() >= 0
62 | }
63 |
64 | // Int returns the int value, which is not necessarily the same as the ordinal.
65 | // This facilitates polymorphism (see enum.IntEnum).
66 | func (v Season_Ic_Si) Int() int {
67 | return int(v)
68 | }
69 |
70 | var invalidSeason_Ic_SiValue = func() Season_Ic_Si {
71 | var v Season_Ic_Si
72 | for {
73 | if !slices.Contains(AllSeason_Ic_Sis, v) {
74 | return v
75 | }
76 | v++
77 | } // AllSeason_Ic_Sis is a finite set so loop will terminate eventually
78 | }()
79 |
80 | // Season_Ic_SiOf returns a Season_Ic_Si based on an ordinal number. This is the inverse of Ordinal.
81 | // If the ordinal is out of range, an invalid Season_Ic_Si is returned.
82 | func Season_Ic_SiOf(v int) Season_Ic_Si {
83 | if 0 <= v && v < len(AllSeason_Ic_Sis) {
84 | return AllSeason_Ic_Sis[v]
85 | }
86 | return invalidSeason_Ic_SiValue
87 | }
88 |
89 | // Parse parses a string to find the corresponding Season_Ic_Si, accepting one of the string values or
90 | // a number. It is used by AsSeason_Ic_Si.
91 | // The input case does not matter.
92 | //
93 | // Usage Example
94 | //
95 | // v := new(Season_Ic_Si)
96 | // err := v.Parse(s)
97 | // ... etc
98 | func (v *Season_Ic_Si) Parse(in string) error {
99 | if v.parseNumber(in) {
100 | return nil
101 | }
102 |
103 | s := season_ic_siTransformInput(in)
104 |
105 | return v.parseFallback(in, s)
106 | }
107 |
108 | // parseNumber attempts to convert a decimal value.
109 | // Only numbers that correspond to the enumeration are valid.
110 | func (v *Season_Ic_Si) parseNumber(s string) (ok bool) {
111 | num, err := strconv.ParseInt(s, 10, 64)
112 | if err == nil {
113 | *v = Season_Ic_Si(num)
114 | return v.IsValid()
115 | }
116 | return false
117 | }
118 |
119 | func (v *Season_Ic_Si) parseFallback(in, s string) error {
120 | if v.parseString(s, season_ic_siEnumInputs, season_ic_siEnumIndex[:]) {
121 | return nil
122 | }
123 |
124 | return errors.New(in + ": unrecognised season_ic_si")
125 | }
126 |
127 | func (v *Season_Ic_Si) parseString(s string, concats string, indexes []uint16) (ok bool) {
128 | var i0 uint16 = 0
129 |
130 | for j := 1; j < len(indexes); j++ {
131 | i1 := indexes[j]
132 | p := concats[i0:i1]
133 | if s == p {
134 | *v = AllSeason_Ic_Sis[j-1]
135 | return true
136 | }
137 | i0 = i1
138 | }
139 | return false
140 | }
141 |
142 | // season_ic_siTransformInput may alter input strings before they are parsed.
143 | // This function is pluggable and is initialised using command-line flags
144 | // -ic -lc -uc -unsnake.
145 | var season_ic_siTransformInput = func(in string) string {
146 | return strings.ToLower(in)
147 | }
148 |
149 | // AsSeason_Ic_Si parses a string to find the corresponding Season_Ic_Si, accepting either one of the string values or
150 | // a number. It wraps Parse.
151 | // The input case does not matter.
152 | func AsSeason_Ic_Si(s string) (Season_Ic_Si, error) {
153 | var v = new(Season_Ic_Si)
154 | err := v.Parse(s)
155 | return *v, err
156 | }
157 |
158 | // MustParseSeason_Ic_Si is similar to AsSeason_Ic_Si except that it panics on error.
159 | // The input case does not matter.
160 | func MustParseSeason_Ic_Si(s string) Season_Ic_Si {
161 | v, err := AsSeason_Ic_Si(s)
162 | if err != nil {
163 | panic(err)
164 | }
165 | return v
166 | }
167 |
168 | // Scan parses some value, which can be a number, a string or []byte.
169 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
170 | func (v *Season_Ic_Si) Scan(value interface{}) error {
171 | if value == nil {
172 | return nil
173 | }
174 |
175 | var s string
176 | switch x := value.(type) {
177 | case int64:
178 | *v = Season_Ic_Si(x)
179 | return v.errorIfInvalid()
180 | case float64:
181 | *v = Season_Ic_Si(x)
182 | return v.errorIfInvalid()
183 | case []byte:
184 | s = string(x)
185 | case string:
186 | s = x
187 | default:
188 | return fmt.Errorf("%T %+v is not a meaningful season_ic_si", value, value)
189 | }
190 |
191 | return v.scanParse(s)
192 | }
193 |
194 | func (v Season_Ic_Si) errorIfInvalid() error {
195 | if v.IsValid() {
196 | return nil
197 | }
198 | return v.invalidError()
199 | }
200 |
201 | func (v Season_Ic_Si) invalidError() error {
202 | return fmt.Errorf("%d is not a valid season_ic_si", v)
203 | }
204 |
205 | func (v *Season_Ic_Si) scanParse(in string) error {
206 | if v.parseNumber(in) {
207 | return nil
208 | }
209 |
210 | s := season_ic_siTransformInput(in)
211 |
212 | return v.parseFallback(in, s)
213 | }
214 |
215 | // Value converts the Season_Ic_Si to a string (based on '-store identifier').
216 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
217 | func (v Season_Ic_Si) Value() (driver.Value, error) {
218 | if !v.IsValid() {
219 | return nil, fmt.Errorf("%v: cannot be stored", v)
220 | }
221 |
222 | return v.String(), nil
223 | }
224 |
--------------------------------------------------------------------------------
/internal/test/season_ic_sn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | // AllSeason_Ic_Sns lists all 4 values in order.
16 | var AllSeason_Ic_Sns = []Season_Ic_Sn{
17 | Spring_Ic_Sn, Summer_Ic_Sn, Autumn_Ic_Sn, Winter_Ic_Sn,
18 | }
19 |
20 | const (
21 | season_ic_snEnumStrings = "SpringSummerAutumnWinter"
22 | season_ic_snEnumInputs = "springsummerautumnwinter"
23 | )
24 |
25 | var (
26 | season_ic_snEnumIndex = [...]uint16{0, 6, 12, 18, 24}
27 | )
28 |
29 | // String returns the literal string representation of a Season_Ic_Sn, which is
30 | // the same as the const identifier but without prefix or suffix.
31 | func (v Season_Ic_Sn) String() string {
32 | o := v.Ordinal()
33 | return v.toString(o, season_ic_snEnumStrings, season_ic_snEnumIndex[:])
34 | }
35 |
36 | // Ordinal returns the ordinal number of a Season_Ic_Sn. This is an integer counting
37 | // from zero. It is *not* the same as the const number assigned to the value.
38 | func (v Season_Ic_Sn) Ordinal() int {
39 | switch v {
40 | case Spring_Ic_Sn:
41 | return 0
42 | case Summer_Ic_Sn:
43 | return 1
44 | case Autumn_Ic_Sn:
45 | return 2
46 | case Winter_Ic_Sn:
47 | return 3
48 | }
49 | return -1
50 | }
51 |
52 | func (v Season_Ic_Sn) toString(o int, concats string, indexes []uint16) string {
53 | if o < 0 || o >= len(AllSeason_Ic_Sns) {
54 | return fmt.Sprintf("Season_Ic_Sn(%d)", v)
55 | }
56 | return concats[indexes[o]:indexes[o+1]]
57 | }
58 |
59 | // IsValid determines whether a Season_Ic_Sn is one of the defined constants.
60 | func (v Season_Ic_Sn) IsValid() bool {
61 | return v.Ordinal() >= 0
62 | }
63 |
64 | // Int returns the int value, which is not necessarily the same as the ordinal.
65 | // This facilitates polymorphism (see enum.IntEnum).
66 | func (v Season_Ic_Sn) Int() int {
67 | return int(v)
68 | }
69 |
70 | var invalidSeason_Ic_SnValue = func() Season_Ic_Sn {
71 | var v Season_Ic_Sn
72 | for {
73 | if !slices.Contains(AllSeason_Ic_Sns, v) {
74 | return v
75 | }
76 | v++
77 | } // AllSeason_Ic_Sns is a finite set so loop will terminate eventually
78 | }()
79 |
80 | // Season_Ic_SnOf returns a Season_Ic_Sn based on an ordinal number. This is the inverse of Ordinal.
81 | // If the ordinal is out of range, an invalid Season_Ic_Sn is returned.
82 | func Season_Ic_SnOf(v int) Season_Ic_Sn {
83 | if 0 <= v && v < len(AllSeason_Ic_Sns) {
84 | return AllSeason_Ic_Sns[v]
85 | }
86 | return invalidSeason_Ic_SnValue
87 | }
88 |
89 | // Parse parses a string to find the corresponding Season_Ic_Sn, accepting one of the string values or
90 | // a number. It is used by AsSeason_Ic_Sn.
91 | // The input case does not matter.
92 | //
93 | // Usage Example
94 | //
95 | // v := new(Season_Ic_Sn)
96 | // err := v.Parse(s)
97 | // ... etc
98 | func (v *Season_Ic_Sn) Parse(in string) error {
99 | if v.parseNumber(in) {
100 | return nil
101 | }
102 |
103 | s := season_ic_snTransformInput(in)
104 |
105 | return v.parseFallback(in, s)
106 | }
107 |
108 | // parseNumber attempts to convert a decimal value.
109 | // Only numbers that correspond to the enumeration are valid.
110 | func (v *Season_Ic_Sn) parseNumber(s string) (ok bool) {
111 | num, err := strconv.ParseInt(s, 10, 64)
112 | if err == nil {
113 | *v = Season_Ic_Sn(num)
114 | return v.IsValid()
115 | }
116 | return false
117 | }
118 |
119 | func (v *Season_Ic_Sn) parseFallback(in, s string) error {
120 | if v.parseString(s, season_ic_snEnumInputs, season_ic_snEnumIndex[:]) {
121 | return nil
122 | }
123 |
124 | return errors.New(in + ": unrecognised season_ic_sn")
125 | }
126 |
127 | func (v *Season_Ic_Sn) parseString(s string, concats string, indexes []uint16) (ok bool) {
128 | var i0 uint16 = 0
129 |
130 | for j := 1; j < len(indexes); j++ {
131 | i1 := indexes[j]
132 | p := concats[i0:i1]
133 | if s == p {
134 | *v = AllSeason_Ic_Sns[j-1]
135 | return true
136 | }
137 | i0 = i1
138 | }
139 | return false
140 | }
141 |
142 | // season_ic_snTransformInput may alter input strings before they are parsed.
143 | // This function is pluggable and is initialised using command-line flags
144 | // -ic -lc -uc -unsnake.
145 | var season_ic_snTransformInput = func(in string) string {
146 | return strings.ToLower(in)
147 | }
148 |
149 | // AsSeason_Ic_Sn parses a string to find the corresponding Season_Ic_Sn, accepting either one of the string values or
150 | // a number. It wraps Parse.
151 | // The input case does not matter.
152 | func AsSeason_Ic_Sn(s string) (Season_Ic_Sn, error) {
153 | var v = new(Season_Ic_Sn)
154 | err := v.Parse(s)
155 | return *v, err
156 | }
157 |
158 | // MustParseSeason_Ic_Sn is similar to AsSeason_Ic_Sn except that it panics on error.
159 | // The input case does not matter.
160 | func MustParseSeason_Ic_Sn(s string) Season_Ic_Sn {
161 | v, err := AsSeason_Ic_Sn(s)
162 | if err != nil {
163 | panic(err)
164 | }
165 | return v
166 | }
167 |
168 | // Scan parses some value, which can be a number, a string or []byte.
169 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
170 | func (v *Season_Ic_Sn) Scan(value interface{}) error {
171 | if value == nil {
172 | return nil
173 | }
174 |
175 | var s string
176 | switch x := value.(type) {
177 | case int64:
178 | *v = Season_Ic_Sn(x)
179 | return v.errorIfInvalid()
180 | case float64:
181 | *v = Season_Ic_Sn(x)
182 | return v.errorIfInvalid()
183 | case []byte:
184 | s = string(x)
185 | case string:
186 | s = x
187 | default:
188 | return fmt.Errorf("%T %+v is not a meaningful season_ic_sn", value, value)
189 | }
190 |
191 | return v.scanParse(s)
192 | }
193 |
194 | func (v Season_Ic_Sn) errorIfInvalid() error {
195 | if v.IsValid() {
196 | return nil
197 | }
198 | return v.invalidError()
199 | }
200 |
201 | func (v Season_Ic_Sn) invalidError() error {
202 | return fmt.Errorf("%d is not a valid season_ic_sn", v)
203 | }
204 |
205 | func (v *Season_Ic_Sn) scanParse(in string) error {
206 | if v.parseNumber(in) {
207 | return nil
208 | }
209 |
210 | s := season_ic_snTransformInput(in)
211 |
212 | return v.parseFallback(in, s)
213 | }
214 |
215 | // Value converts the Season_Ic_Sn to a number (based on '-store number').
216 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
217 | func (v Season_Ic_Sn) Value() (driver.Value, error) {
218 | return int64(v), nil
219 | }
220 |
--------------------------------------------------------------------------------
/internal/test/season_json.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Ji -suffix _Nc_Ji -marshaljson identifier
4 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Jn -suffix _Nc_Jn -marshaljson number
5 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Jj -suffix _Nc_Jj
6 |
7 | type (
8 | Season_Nc_Ji uint
9 | Season_Nc_Jn uint
10 | Season_Nc_Jj uint
11 | )
12 |
13 | const (
14 | Spring_Nc_Ji, Summer_Nc_Ji, Autumn_Nc_Ji, Winter_Nc_Ji Season_Nc_Ji = 1, 2, 3, 4
15 | )
16 |
17 | const (
18 | Spring_Nc_Jn, Summer_Nc_Jn, Autumn_Nc_Jn, Winter_Nc_Jn Season_Nc_Jn = 1, 2, 3, 4
19 | )
20 |
21 | const (
22 | _ Season_Nc_Jj = iota
23 | Spring_Nc_Jj // json:"Sprg"
24 | Summer_Nc_Jj // json:"Sumr"
25 | Autumn_Nc_Jj // json:"Autm"
26 | Winter_Nc_Jj // json:"Wint"
27 | )
28 |
29 | //=================================================================================================
30 | //go:generate enumeration -v -f -i season_json.go -type Season_Ic_Ji -suffix _Ic_Ji -ic -marshaljson identifier
31 | //go:generate enumeration -v -f -i season_json.go -type Season_Ic_Jn -suffix _Ic_Jn -ic -marshaljson number
32 | //go:generate enumeration -v -f -i season_json.go -type Season_Ic_Jj -suffix _Ic_Jj -ic
33 |
34 | type (
35 | Season_Ic_Ji uint
36 | Season_Ic_Jn uint
37 | Season_Ic_Jj uint
38 | )
39 |
40 | const (
41 | Spring_Ic_Ji, Summer_Ic_Ji, Autumn_Ic_Ji, Winter_Ic_Ji Season_Ic_Ji = 1, 2, 3, 4
42 | )
43 |
44 | const (
45 | Spring_Ic_Jn, Summer_Ic_Jn, Autumn_Ic_Jn, Winter_Ic_Jn Season_Ic_Jn = 1, 2, 3, 4
46 | )
47 |
48 | const (
49 | _ Season_Ic_Jj = iota
50 | Spring_Ic_Jj // json:"Sprg"
51 | Summer_Ic_Jj // json:"Sumr"
52 | Autumn_Ic_Jj // json:"Autm"
53 | Winter_Ic_Jj // json:"Wint"
54 | )
55 |
56 | //=================================================================================================
57 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Ji -suffix _Uc_Ji -uc -marshaljson identifier
58 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Jn -suffix _Uc_Jn -uc -marshaljson number
59 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Jj -suffix _Uc_Jj -uc
60 |
61 | type (
62 | Season_Uc_Ji uint
63 | Season_Uc_Jn uint
64 | Season_Uc_Jj uint
65 | )
66 |
67 | const (
68 | Spring_Uc_Ji, Summer_Uc_Ji, Autumn_Uc_Ji, Winter_Uc_Ji Season_Uc_Ji = 1, 2, 3, 4
69 | )
70 |
71 | const (
72 | _ Season_Uc_Jn = iota
73 | Spring_Uc_Jn
74 | Summer_Uc_Jn
75 | Autumn_Uc_Jn // 3
76 | Winter_Uc_Jn
77 | )
78 |
79 | const (
80 | _ Season_Uc_Jj = iota
81 | Spring_Uc_Jj // json:"Sprg"
82 | Summer_Uc_Jj // json:"Sumr"
83 | Autumn_Uc_Jj // json:"Autm"
84 | Winter_Uc_Jj // json:"Wint"
85 | )
86 |
--------------------------------------------------------------------------------
/internal/test/season_nc_jn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Nc_Jns lists all 4 values in order.
15 | var AllSeason_Nc_Jns = []Season_Nc_Jn{
16 | Spring_Nc_Jn, Summer_Nc_Jn, Autumn_Nc_Jn, Winter_Nc_Jn,
17 | }
18 |
19 | const (
20 | season_nc_jnEnumStrings = "SpringSummerAutumnWinter"
21 | )
22 |
23 | var (
24 | season_nc_jnEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Nc_Jn, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Nc_Jn) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_nc_jnEnumStrings, season_nc_jnEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Nc_Jn. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Nc_Jn) Ordinal() int {
37 | switch v {
38 | case Spring_Nc_Jn:
39 | return 0
40 | case Summer_Nc_Jn:
41 | return 1
42 | case Autumn_Nc_Jn:
43 | return 2
44 | case Winter_Nc_Jn:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Nc_Jn) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Nc_Jns) {
52 | return fmt.Sprintf("Season_Nc_Jn(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Nc_Jn is one of the defined constants.
58 | func (v Season_Nc_Jn) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Nc_Jn) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Nc_JnValue = func() Season_Nc_Jn {
69 | var v Season_Nc_Jn
70 | for {
71 | if !slices.Contains(AllSeason_Nc_Jns, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Nc_Jns is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Nc_JnOf returns a Season_Nc_Jn based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Nc_Jn is returned.
80 | func Season_Nc_JnOf(v int) Season_Nc_Jn {
81 | if 0 <= v && v < len(AllSeason_Nc_Jns) {
82 | return AllSeason_Nc_Jns[v]
83 | }
84 | return invalidSeason_Nc_JnValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Nc_Jn, accepting one of the string values or
88 | // a number. It is used by AsSeason_Nc_Jn.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Nc_Jn)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Nc_Jn) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_nc_jnTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Nc_Jn) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Nc_Jn(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Nc_Jn) parseFallback(in, s string) error {
117 | if v.parseString(s, season_nc_jnEnumStrings, season_nc_jnEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_nc_jn")
122 | }
123 |
124 | func (v *Season_Nc_Jn) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Nc_Jns[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_nc_jnTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_nc_jnTransformInput = func(in string) string {
143 | return in
144 | }
145 |
146 | // AsSeason_Nc_Jn parses a string to find the corresponding Season_Nc_Jn, accepting either one of the string values or
147 | // a number. It wraps Parse.
148 | func AsSeason_Nc_Jn(s string) (Season_Nc_Jn, error) {
149 | var v = new(Season_Nc_Jn)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Nc_Jn is similar to AsSeason_Nc_Jn except that it panics on error.
155 | func MustParseSeason_Nc_Jn(s string) Season_Nc_Jn {
156 | v, err := AsSeason_Nc_Jn(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // MarshalJSON converts values to bytes suitable for transmission via JSON.
164 | // The number representation is chosen according to -marshaljson.
165 | func (v Season_Nc_Jn) MarshalJSON() ([]byte, error) {
166 | if !v.IsValid() {
167 | return v.marshalNumberOrError()
168 | }
169 |
170 | s := season_nc_jnMarshalNumber(v)
171 | return []byte(s), nil
172 | }
173 |
174 | func (v Season_Nc_Jn) marshalNumberOrError() ([]byte, error) {
175 | // disallow lenient marshaling
176 | return nil, v.invalidError()
177 | }
178 |
179 | func (v Season_Nc_Jn) invalidError() error {
180 | return fmt.Errorf("%d is not a valid season_nc_jn", v)
181 | }
182 |
183 | // season_nc_jnMarshalNumber handles marshaling where a number is required or where
184 | // the value is out of range.
185 | // This function can be replaced with any bespoke function than matches signature.
186 | var season_nc_jnMarshalNumber = func(v Season_Nc_Jn) string {
187 | return strconv.FormatInt(int64(v), 10)
188 | }
189 |
190 | // UnmarshalJSON converts transmitted JSON values to ordinary values. It allows both
191 | // ordinals and strings to represent the values.
192 | func (v *Season_Nc_Jn) UnmarshalJSON(text []byte) error {
193 | s := string(text)
194 | if s == "null" {
195 | // Ignore null, like in the main JSON package.
196 | return nil
197 | }
198 | s = strings.Trim(s, "\"")
199 | return v.unmarshalJSON(s)
200 | }
201 |
202 | func (v *Season_Nc_Jn) unmarshalJSON(in string) error {
203 | if v.parseNumber(in) {
204 | return nil
205 | }
206 |
207 | s := season_nc_jnTransformInput(in)
208 |
209 | if v.parseString(s, season_nc_jnEnumStrings, season_nc_jnEnumIndex[:]) {
210 | return nil
211 | }
212 |
213 | return errors.New(in + ": unrecognised season_nc_jn")
214 | }
215 |
--------------------------------------------------------------------------------
/internal/test/season_nc_si_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | )
13 |
14 | // AllSeason_Nc_Sis lists all 4 values in order.
15 | var AllSeason_Nc_Sis = []Season_Nc_Si{
16 | Spring_Nc_Si, Summer_Nc_Si, Autumn_Nc_Si, Winter_Nc_Si,
17 | }
18 |
19 | const (
20 | season_nc_siEnumStrings = "SpringSummerAutumnWinter"
21 | )
22 |
23 | var (
24 | season_nc_siEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Nc_Si, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Nc_Si) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_nc_siEnumStrings, season_nc_siEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Nc_Si. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Nc_Si) Ordinal() int {
37 | switch v {
38 | case Spring_Nc_Si:
39 | return 0
40 | case Summer_Nc_Si:
41 | return 1
42 | case Autumn_Nc_Si:
43 | return 2
44 | case Winter_Nc_Si:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Nc_Si) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Nc_Sis) {
52 | return fmt.Sprintf("Season_Nc_Si(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Nc_Si is one of the defined constants.
58 | func (v Season_Nc_Si) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Nc_Si) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Nc_SiValue = func() Season_Nc_Si {
69 | var v Season_Nc_Si
70 | for {
71 | if !slices.Contains(AllSeason_Nc_Sis, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Nc_Sis is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Nc_SiOf returns a Season_Nc_Si based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Nc_Si is returned.
80 | func Season_Nc_SiOf(v int) Season_Nc_Si {
81 | if 0 <= v && v < len(AllSeason_Nc_Sis) {
82 | return AllSeason_Nc_Sis[v]
83 | }
84 | return invalidSeason_Nc_SiValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Nc_Si, accepting one of the string values or
88 | // a number. It is used by AsSeason_Nc_Si.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Nc_Si)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Nc_Si) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_nc_siTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Nc_Si) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Nc_Si(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Nc_Si) parseFallback(in, s string) error {
117 | if v.parseString(s, season_nc_siEnumStrings, season_nc_siEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_nc_si")
122 | }
123 |
124 | func (v *Season_Nc_Si) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Nc_Sis[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_nc_siTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_nc_siTransformInput = func(in string) string {
143 | return in
144 | }
145 |
146 | // AsSeason_Nc_Si parses a string to find the corresponding Season_Nc_Si, accepting either one of the string values or
147 | // a number. It wraps Parse.
148 | func AsSeason_Nc_Si(s string) (Season_Nc_Si, error) {
149 | var v = new(Season_Nc_Si)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Nc_Si is similar to AsSeason_Nc_Si except that it panics on error.
155 | func MustParseSeason_Nc_Si(s string) Season_Nc_Si {
156 | v, err := AsSeason_Nc_Si(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // Scan parses some value, which can be a number, a string or []byte.
164 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
165 | func (v *Season_Nc_Si) Scan(value interface{}) error {
166 | if value == nil {
167 | return nil
168 | }
169 |
170 | var s string
171 | switch x := value.(type) {
172 | case int64:
173 | *v = Season_Nc_Si(x)
174 | return v.errorIfInvalid()
175 | case float64:
176 | *v = Season_Nc_Si(x)
177 | return v.errorIfInvalid()
178 | case []byte:
179 | s = string(x)
180 | case string:
181 | s = x
182 | default:
183 | return fmt.Errorf("%T %+v is not a meaningful season_nc_si", value, value)
184 | }
185 |
186 | return v.scanParse(s)
187 | }
188 |
189 | func (v Season_Nc_Si) errorIfInvalid() error {
190 | if v.IsValid() {
191 | return nil
192 | }
193 | return v.invalidError()
194 | }
195 |
196 | func (v Season_Nc_Si) invalidError() error {
197 | return fmt.Errorf("%d is not a valid season_nc_si", v)
198 | }
199 |
200 | func (v *Season_Nc_Si) scanParse(in string) error {
201 | if v.parseNumber(in) {
202 | return nil
203 | }
204 |
205 | s := season_nc_siTransformInput(in)
206 |
207 | return v.parseFallback(in, s)
208 | }
209 |
210 | // Value converts the Season_Nc_Si to a string (based on '-store identifier').
211 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
212 | func (v Season_Nc_Si) Value() (driver.Value, error) {
213 | if !v.IsValid() {
214 | return nil, fmt.Errorf("%v: cannot be stored", v)
215 | }
216 |
217 | return v.String(), nil
218 | }
219 |
--------------------------------------------------------------------------------
/internal/test/season_nc_sn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | )
13 |
14 | // AllSeason_Nc_Sns lists all 4 values in order.
15 | var AllSeason_Nc_Sns = []Season_Nc_Sn{
16 | Spring_Nc_Sn, Summer_Nc_Sn, Autumn_Nc_Sn, Winter_Nc_Sn,
17 | }
18 |
19 | const (
20 | season_nc_snEnumStrings = "SpringSummerAutumnWinter"
21 | )
22 |
23 | var (
24 | season_nc_snEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Nc_Sn, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Nc_Sn) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_nc_snEnumStrings, season_nc_snEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Nc_Sn. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Nc_Sn) Ordinal() int {
37 | switch v {
38 | case Spring_Nc_Sn:
39 | return 0
40 | case Summer_Nc_Sn:
41 | return 1
42 | case Autumn_Nc_Sn:
43 | return 2
44 | case Winter_Nc_Sn:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Nc_Sn) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Nc_Sns) {
52 | return fmt.Sprintf("Season_Nc_Sn(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Nc_Sn is one of the defined constants.
58 | func (v Season_Nc_Sn) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Nc_Sn) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Nc_SnValue = func() Season_Nc_Sn {
69 | var v Season_Nc_Sn
70 | for {
71 | if !slices.Contains(AllSeason_Nc_Sns, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Nc_Sns is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Nc_SnOf returns a Season_Nc_Sn based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Nc_Sn is returned.
80 | func Season_Nc_SnOf(v int) Season_Nc_Sn {
81 | if 0 <= v && v < len(AllSeason_Nc_Sns) {
82 | return AllSeason_Nc_Sns[v]
83 | }
84 | return invalidSeason_Nc_SnValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Nc_Sn, accepting one of the string values or
88 | // a number. It is used by AsSeason_Nc_Sn.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Nc_Sn)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Nc_Sn) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_nc_snTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Nc_Sn) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Nc_Sn(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Nc_Sn) parseFallback(in, s string) error {
117 | if v.parseString(s, season_nc_snEnumStrings, season_nc_snEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_nc_sn")
122 | }
123 |
124 | func (v *Season_Nc_Sn) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Nc_Sns[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_nc_snTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_nc_snTransformInput = func(in string) string {
143 | return in
144 | }
145 |
146 | // AsSeason_Nc_Sn parses a string to find the corresponding Season_Nc_Sn, accepting either one of the string values or
147 | // a number. It wraps Parse.
148 | func AsSeason_Nc_Sn(s string) (Season_Nc_Sn, error) {
149 | var v = new(Season_Nc_Sn)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Nc_Sn is similar to AsSeason_Nc_Sn except that it panics on error.
155 | func MustParseSeason_Nc_Sn(s string) Season_Nc_Sn {
156 | v, err := AsSeason_Nc_Sn(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // Scan parses some value, which can be a number, a string or []byte.
164 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
165 | func (v *Season_Nc_Sn) Scan(value interface{}) error {
166 | if value == nil {
167 | return nil
168 | }
169 |
170 | var s string
171 | switch x := value.(type) {
172 | case int64:
173 | *v = Season_Nc_Sn(x)
174 | return v.errorIfInvalid()
175 | case float64:
176 | *v = Season_Nc_Sn(x)
177 | return v.errorIfInvalid()
178 | case []byte:
179 | s = string(x)
180 | case string:
181 | s = x
182 | default:
183 | return fmt.Errorf("%T %+v is not a meaningful season_nc_sn", value, value)
184 | }
185 |
186 | return v.scanParse(s)
187 | }
188 |
189 | func (v Season_Nc_Sn) errorIfInvalid() error {
190 | if v.IsValid() {
191 | return nil
192 | }
193 | return v.invalidError()
194 | }
195 |
196 | func (v Season_Nc_Sn) invalidError() error {
197 | return fmt.Errorf("%d is not a valid season_nc_sn", v)
198 | }
199 |
200 | func (v *Season_Nc_Sn) scanParse(in string) error {
201 | if v.parseNumber(in) {
202 | return nil
203 | }
204 |
205 | s := season_nc_snTransformInput(in)
206 |
207 | return v.parseFallback(in, s)
208 | }
209 |
210 | // Value converts the Season_Nc_Sn to a number (based on '-store number').
211 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
212 | func (v Season_Nc_Sn) Value() (driver.Value, error) {
213 | return int64(v), nil
214 | }
215 |
--------------------------------------------------------------------------------
/internal/test/season_nc_ss_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | )
13 |
14 | // AllSeason_Nc_Sss lists all 4 values in order.
15 | var AllSeason_Nc_Sss = []Season_Nc_Ss{
16 | Spring_Nc_Ss, Summer_Nc_Ss, Autumn_Nc_Ss, Winter_Nc_Ss,
17 | }
18 |
19 | const (
20 | season_nc_ssEnumStrings = "SpringSummerAutumnWinter"
21 | season_nc_ssSQLStrings = "SprgSumrAutmWint"
22 | )
23 |
24 | var (
25 | season_nc_ssEnumIndex = [...]uint16{0, 6, 12, 18, 24}
26 | season_nc_ssSQLIndex = [...]uint16{0, 4, 8, 12, 16}
27 | )
28 |
29 | // String returns the literal string representation of a Season_Nc_Ss, which is
30 | // the same as the const identifier but without prefix or suffix.
31 | func (v Season_Nc_Ss) String() string {
32 | o := v.Ordinal()
33 | return v.toString(o, season_nc_ssEnumStrings, season_nc_ssEnumIndex[:])
34 | }
35 |
36 | // Ordinal returns the ordinal number of a Season_Nc_Ss. This is an integer counting
37 | // from zero. It is *not* the same as the const number assigned to the value.
38 | func (v Season_Nc_Ss) Ordinal() int {
39 | switch v {
40 | case Spring_Nc_Ss:
41 | return 0
42 | case Summer_Nc_Ss:
43 | return 1
44 | case Autumn_Nc_Ss:
45 | return 2
46 | case Winter_Nc_Ss:
47 | return 3
48 | }
49 | return -1
50 | }
51 |
52 | func (v Season_Nc_Ss) toString(o int, concats string, indexes []uint16) string {
53 | if o < 0 || o >= len(AllSeason_Nc_Sss) {
54 | return fmt.Sprintf("Season_Nc_Ss(%d)", v)
55 | }
56 | return concats[indexes[o]:indexes[o+1]]
57 | }
58 |
59 | // IsValid determines whether a Season_Nc_Ss is one of the defined constants.
60 | func (v Season_Nc_Ss) IsValid() bool {
61 | return v.Ordinal() >= 0
62 | }
63 |
64 | // Int returns the int value, which is not necessarily the same as the ordinal.
65 | // This facilitates polymorphism (see enum.IntEnum).
66 | func (v Season_Nc_Ss) Int() int {
67 | return int(v)
68 | }
69 |
70 | var invalidSeason_Nc_SsValue = func() Season_Nc_Ss {
71 | var v Season_Nc_Ss
72 | for {
73 | if !slices.Contains(AllSeason_Nc_Sss, v) {
74 | return v
75 | }
76 | v++
77 | } // AllSeason_Nc_Sss is a finite set so loop will terminate eventually
78 | }()
79 |
80 | // Season_Nc_SsOf returns a Season_Nc_Ss based on an ordinal number. This is the inverse of Ordinal.
81 | // If the ordinal is out of range, an invalid Season_Nc_Ss is returned.
82 | func Season_Nc_SsOf(v int) Season_Nc_Ss {
83 | if 0 <= v && v < len(AllSeason_Nc_Sss) {
84 | return AllSeason_Nc_Sss[v]
85 | }
86 | return invalidSeason_Nc_SsValue
87 | }
88 |
89 | // Parse parses a string to find the corresponding Season_Nc_Ss, accepting one of the string values or
90 | // a number. It is used by AsSeason_Nc_Ss.
91 | //
92 | // Usage Example
93 | //
94 | // v := new(Season_Nc_Ss)
95 | // err := v.Parse(s)
96 | // ... etc
97 | func (v *Season_Nc_Ss) Parse(in string) error {
98 | if v.parseNumber(in) {
99 | return nil
100 | }
101 |
102 | s := season_nc_ssTransformInput(in)
103 |
104 | return v.parseFallback(in, s)
105 | }
106 |
107 | // parseNumber attempts to convert a decimal value.
108 | // Only numbers that correspond to the enumeration are valid.
109 | func (v *Season_Nc_Ss) parseNumber(s string) (ok bool) {
110 | num, err := strconv.ParseInt(s, 10, 64)
111 | if err == nil {
112 | *v = Season_Nc_Ss(num)
113 | return v.IsValid()
114 | }
115 | return false
116 | }
117 |
118 | func (v *Season_Nc_Ss) parseFallback(in, s string) error {
119 | if v.parseString(s, season_nc_ssEnumStrings, season_nc_ssEnumIndex[:]) {
120 | return nil
121 | }
122 |
123 | return errors.New(in + ": unrecognised season_nc_ss")
124 | }
125 |
126 | func (v *Season_Nc_Ss) parseString(s string, concats string, indexes []uint16) (ok bool) {
127 | var i0 uint16 = 0
128 |
129 | for j := 1; j < len(indexes); j++ {
130 | i1 := indexes[j]
131 | p := concats[i0:i1]
132 | if s == p {
133 | *v = AllSeason_Nc_Sss[j-1]
134 | return true
135 | }
136 | i0 = i1
137 | }
138 | return false
139 | }
140 |
141 | // season_nc_ssTransformInput may alter input strings before they are parsed.
142 | // This function is pluggable and is initialised using command-line flags
143 | // -ic -lc -uc -unsnake.
144 | var season_nc_ssTransformInput = func(in string) string {
145 | return in
146 | }
147 |
148 | // AsSeason_Nc_Ss parses a string to find the corresponding Season_Nc_Ss, accepting either one of the string values or
149 | // a number. It wraps Parse.
150 | func AsSeason_Nc_Ss(s string) (Season_Nc_Ss, error) {
151 | var v = new(Season_Nc_Ss)
152 | err := v.Parse(s)
153 | return *v, err
154 | }
155 |
156 | // MustParseSeason_Nc_Ss is similar to AsSeason_Nc_Ss except that it panics on error.
157 | func MustParseSeason_Nc_Ss(s string) Season_Nc_Ss {
158 | v, err := AsSeason_Nc_Ss(s)
159 | if err != nil {
160 | panic(err)
161 | }
162 | return v
163 | }
164 |
165 | // Scan parses some value, which can be a number, a string or []byte.
166 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
167 | func (v *Season_Nc_Ss) Scan(value interface{}) error {
168 | if value == nil {
169 | return nil
170 | }
171 |
172 | var s string
173 | switch x := value.(type) {
174 | case int64:
175 | *v = Season_Nc_Ss(x)
176 | return v.errorIfInvalid()
177 | case float64:
178 | *v = Season_Nc_Ss(x)
179 | return v.errorIfInvalid()
180 | case []byte:
181 | s = string(x)
182 | case string:
183 | s = x
184 | default:
185 | return fmt.Errorf("%T %+v is not a meaningful season_nc_ss", value, value)
186 | }
187 |
188 | return v.scanParse(s)
189 | }
190 |
191 | func (v Season_Nc_Ss) errorIfInvalid() error {
192 | if v.IsValid() {
193 | return nil
194 | }
195 | return v.invalidError()
196 | }
197 |
198 | func (v Season_Nc_Ss) invalidError() error {
199 | return fmt.Errorf("%d is not a valid season_nc_ss", v)
200 | }
201 |
202 | func (v *Season_Nc_Ss) scanParse(in string) error {
203 | if v.parseNumber(in) {
204 | return nil
205 | }
206 |
207 | s := season_nc_ssTransformInput(in)
208 |
209 | if v.parseString(s, season_nc_ssSQLStrings, season_nc_ssSQLIndex[:]) {
210 | return nil
211 | }
212 |
213 | return v.parseFallback(in, s)
214 | }
215 |
216 | // Value converts the Season_Nc_Ss to a string.
217 | // The representation is chosen according to 'sql' struct tags.
218 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
219 | func (v Season_Nc_Ss) Value() (driver.Value, error) {
220 | o := v.Ordinal()
221 | if o < 0 {
222 | return nil, fmt.Errorf("%v: cannot be stored", v)
223 | }
224 |
225 | return v.toString(o, season_nc_ssSQLStrings, season_nc_ssSQLIndex[:]), nil
226 | }
227 |
--------------------------------------------------------------------------------
/internal/test/season_nc_ti_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllSeason_Nc_Tis lists all 4 values in order.
14 | var AllSeason_Nc_Tis = []Season_Nc_Ti{
15 | Spring_Nc_Ti, Summer_Nc_Ti, Autumn_Nc_Ti, Winter_Nc_Ti,
16 | }
17 |
18 | const (
19 | season_nc_tiEnumStrings = "SpringSummerAutumnWinter"
20 | )
21 |
22 | var (
23 | season_nc_tiEnumIndex = [...]uint16{0, 6, 12, 18, 24}
24 | )
25 |
26 | // String returns the literal string representation of a Season_Nc_Ti, which is
27 | // the same as the const identifier but without prefix or suffix.
28 | func (v Season_Nc_Ti) String() string {
29 | o := v.Ordinal()
30 | return v.toString(o, season_nc_tiEnumStrings, season_nc_tiEnumIndex[:])
31 | }
32 |
33 | // Ordinal returns the ordinal number of a Season_Nc_Ti. This is an integer counting
34 | // from zero. It is *not* the same as the const number assigned to the value.
35 | func (v Season_Nc_Ti) Ordinal() int {
36 | switch v {
37 | case Spring_Nc_Ti:
38 | return 0
39 | case Summer_Nc_Ti:
40 | return 1
41 | case Autumn_Nc_Ti:
42 | return 2
43 | case Winter_Nc_Ti:
44 | return 3
45 | }
46 | return -1
47 | }
48 |
49 | func (v Season_Nc_Ti) toString(o int, concats string, indexes []uint16) string {
50 | if o < 0 || o >= len(AllSeason_Nc_Tis) {
51 | return fmt.Sprintf("Season_Nc_Ti(%d)", v)
52 | }
53 | return concats[indexes[o]:indexes[o+1]]
54 | }
55 |
56 | // IsValid determines whether a Season_Nc_Ti is one of the defined constants.
57 | func (v Season_Nc_Ti) IsValid() bool {
58 | return v.Ordinal() >= 0
59 | }
60 |
61 | // Int returns the int value, which is not necessarily the same as the ordinal.
62 | // This facilitates polymorphism (see enum.IntEnum).
63 | func (v Season_Nc_Ti) Int() int {
64 | return int(v)
65 | }
66 |
67 | var invalidSeason_Nc_TiValue = func() Season_Nc_Ti {
68 | var v Season_Nc_Ti
69 | for {
70 | if !slices.Contains(AllSeason_Nc_Tis, v) {
71 | return v
72 | }
73 | v++
74 | } // AllSeason_Nc_Tis is a finite set so loop will terminate eventually
75 | }()
76 |
77 | // Season_Nc_TiOf returns a Season_Nc_Ti based on an ordinal number. This is the inverse of Ordinal.
78 | // If the ordinal is out of range, an invalid Season_Nc_Ti is returned.
79 | func Season_Nc_TiOf(v int) Season_Nc_Ti {
80 | if 0 <= v && v < len(AllSeason_Nc_Tis) {
81 | return AllSeason_Nc_Tis[v]
82 | }
83 | return invalidSeason_Nc_TiValue
84 | }
85 |
86 | // Parse parses a string to find the corresponding Season_Nc_Ti, accepting one of the string values or
87 | // a number. The input representation is determined by Identifier. It is used by AsSeason_Nc_Ti.
88 | //
89 | // Usage Example
90 | //
91 | // v := new(Season_Nc_Ti)
92 | // err := v.Parse(s)
93 | // ... etc
94 | func (v *Season_Nc_Ti) Parse(in string) error {
95 | if v.parseNumber(in) {
96 | return nil
97 | }
98 |
99 | s := season_nc_tiTransformInput(in)
100 |
101 | return v.parseFallback(in, s)
102 | }
103 |
104 | // parseNumber attempts to convert a decimal value.
105 | // Only numbers that correspond to the enumeration are valid.
106 | func (v *Season_Nc_Ti) parseNumber(s string) (ok bool) {
107 | num, err := strconv.ParseInt(s, 10, 64)
108 | if err == nil {
109 | *v = Season_Nc_Ti(num)
110 | return v.IsValid()
111 | }
112 | return false
113 | }
114 |
115 | func (v *Season_Nc_Ti) parseFallback(in, s string) error {
116 | if v.parseString(s, season_nc_tiEnumStrings, season_nc_tiEnumIndex[:]) {
117 | return nil
118 | }
119 |
120 | return errors.New(in + ": unrecognised season_nc_ti")
121 | }
122 |
123 | func (v *Season_Nc_Ti) parseString(s string, concats string, indexes []uint16) (ok bool) {
124 | var i0 uint16 = 0
125 |
126 | for j := 1; j < len(indexes); j++ {
127 | i1 := indexes[j]
128 | p := concats[i0:i1]
129 | if s == p {
130 | *v = AllSeason_Nc_Tis[j-1]
131 | return true
132 | }
133 | i0 = i1
134 | }
135 | return false
136 | }
137 |
138 | // season_nc_tiTransformInput may alter input strings before they are parsed.
139 | // This function is pluggable and is initialised using command-line flags
140 | // -ic -lc -uc -unsnake.
141 | var season_nc_tiTransformInput = func(in string) string {
142 | return in
143 | }
144 |
145 | // AsSeason_Nc_Ti parses a string to find the corresponding Season_Nc_Ti, accepting either one of the string values or
146 | // a number. The input representation is determined by season_nc_tiMarshalTextRep. It wraps Parse.
147 | func AsSeason_Nc_Ti(s string) (Season_Nc_Ti, error) {
148 | var v = new(Season_Nc_Ti)
149 | err := v.Parse(s)
150 | return *v, err
151 | }
152 |
153 | // MustParseSeason_Nc_Ti is similar to AsSeason_Nc_Ti except that it panics on error.
154 | func MustParseSeason_Nc_Ti(s string) Season_Nc_Ti {
155 | v, err := AsSeason_Nc_Ti(s)
156 | if err != nil {
157 | panic(err)
158 | }
159 | return v
160 | }
161 |
162 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
163 | func (v Season_Nc_Ti) MarshalText() ([]byte, error) {
164 | s, err := v.marshalText()
165 | return []byte(s), err
166 | }
167 |
168 | // Text returns the representation used for transmission via XML, JSON etc.
169 | func (v Season_Nc_Ti) Text() string {
170 | s, _ := v.marshalText()
171 | return s
172 | }
173 |
174 | // marshalText converts values to a form suitable for transmission via XML, JSON etc.
175 | // The identifier representation is chosen according to -marshaltext.
176 | func (v Season_Nc_Ti) marshalText() (string, error) {
177 | o := v.Ordinal()
178 | if o < 0 {
179 | return v.marshalNumberStringOrError()
180 | }
181 |
182 | return v.toString(o, season_nc_tiEnumStrings, season_nc_tiEnumIndex[:]), nil
183 | }
184 |
185 | func (v Season_Nc_Ti) marshalNumberStringOrError() (string, error) {
186 | bs, err := v.marshalNumberOrError()
187 | return string(bs), err
188 | }
189 |
190 | func (v Season_Nc_Ti) marshalNumberOrError() ([]byte, error) {
191 | // disallow lenient marshaling
192 | return nil, v.invalidError()
193 | }
194 |
195 | func (v Season_Nc_Ti) invalidError() error {
196 | return fmt.Errorf("%d is not a valid season_nc_ti", v)
197 | }
198 |
199 | // UnmarshalText converts transmitted values to ordinary values.
200 | func (v *Season_Nc_Ti) UnmarshalText(bs []byte) error {
201 | return v.unmarshalText(string(bs))
202 | }
203 |
204 | func (v *Season_Nc_Ti) unmarshalText(in string) error {
205 | if v.parseNumber(in) {
206 | return nil
207 | }
208 |
209 | s := season_nc_tiTransformInput(in)
210 |
211 | return v.parseFallback(in, s)
212 | }
213 |
--------------------------------------------------------------------------------
/internal/test/season_nc_tn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllSeason_Nc_Tns lists all 4 values in order.
14 | var AllSeason_Nc_Tns = []Season_Nc_Tn{
15 | Spring_Nc_Tn, Summer_Nc_Tn, Autumn_Nc_Tn, Winter_Nc_Tn,
16 | }
17 |
18 | const (
19 | season_nc_tnEnumStrings = "SpringSummerAutumnWinter"
20 | )
21 |
22 | var (
23 | season_nc_tnEnumIndex = [...]uint16{0, 6, 12, 18, 24}
24 | )
25 |
26 | // String returns the literal string representation of a Season_Nc_Tn, which is
27 | // the same as the const identifier but without prefix or suffix.
28 | func (v Season_Nc_Tn) String() string {
29 | o := v.Ordinal()
30 | return v.toString(o, season_nc_tnEnumStrings, season_nc_tnEnumIndex[:])
31 | }
32 |
33 | // Ordinal returns the ordinal number of a Season_Nc_Tn. This is an integer counting
34 | // from zero. It is *not* the same as the const number assigned to the value.
35 | func (v Season_Nc_Tn) Ordinal() int {
36 | switch v {
37 | case Spring_Nc_Tn:
38 | return 0
39 | case Summer_Nc_Tn:
40 | return 1
41 | case Autumn_Nc_Tn:
42 | return 2
43 | case Winter_Nc_Tn:
44 | return 3
45 | }
46 | return -1
47 | }
48 |
49 | func (v Season_Nc_Tn) toString(o int, concats string, indexes []uint16) string {
50 | if o < 0 || o >= len(AllSeason_Nc_Tns) {
51 | return fmt.Sprintf("Season_Nc_Tn(%d)", v)
52 | }
53 | return concats[indexes[o]:indexes[o+1]]
54 | }
55 |
56 | // IsValid determines whether a Season_Nc_Tn is one of the defined constants.
57 | func (v Season_Nc_Tn) IsValid() bool {
58 | return v.Ordinal() >= 0
59 | }
60 |
61 | // Int returns the int value, which is not necessarily the same as the ordinal.
62 | // This facilitates polymorphism (see enum.IntEnum).
63 | func (v Season_Nc_Tn) Int() int {
64 | return int(v)
65 | }
66 |
67 | var invalidSeason_Nc_TnValue = func() Season_Nc_Tn {
68 | var v Season_Nc_Tn
69 | for {
70 | if !slices.Contains(AllSeason_Nc_Tns, v) {
71 | return v
72 | }
73 | v++
74 | } // AllSeason_Nc_Tns is a finite set so loop will terminate eventually
75 | }()
76 |
77 | // Season_Nc_TnOf returns a Season_Nc_Tn based on an ordinal number. This is the inverse of Ordinal.
78 | // If the ordinal is out of range, an invalid Season_Nc_Tn is returned.
79 | func Season_Nc_TnOf(v int) Season_Nc_Tn {
80 | if 0 <= v && v < len(AllSeason_Nc_Tns) {
81 | return AllSeason_Nc_Tns[v]
82 | }
83 | return invalidSeason_Nc_TnValue
84 | }
85 |
86 | // Parse parses a string to find the corresponding Season_Nc_Tn, accepting one of the string values or
87 | // a number. The input representation is determined by Number. It is used by AsSeason_Nc_Tn.
88 | //
89 | // Usage Example
90 | //
91 | // v := new(Season_Nc_Tn)
92 | // err := v.Parse(s)
93 | // ... etc
94 | func (v *Season_Nc_Tn) Parse(in string) error {
95 | if v.parseNumber(in) {
96 | return nil
97 | }
98 |
99 | s := season_nc_tnTransformInput(in)
100 |
101 | return v.parseFallback(in, s)
102 | }
103 |
104 | // parseNumber attempts to convert a decimal value.
105 | // Only numbers that correspond to the enumeration are valid.
106 | func (v *Season_Nc_Tn) parseNumber(s string) (ok bool) {
107 | num, err := strconv.ParseInt(s, 10, 64)
108 | if err == nil {
109 | *v = Season_Nc_Tn(num)
110 | return v.IsValid()
111 | }
112 | return false
113 | }
114 |
115 | func (v *Season_Nc_Tn) parseFallback(in, s string) error {
116 | if v.parseString(s, season_nc_tnEnumStrings, season_nc_tnEnumIndex[:]) {
117 | return nil
118 | }
119 |
120 | return errors.New(in + ": unrecognised season_nc_tn")
121 | }
122 |
123 | func (v *Season_Nc_Tn) parseString(s string, concats string, indexes []uint16) (ok bool) {
124 | var i0 uint16 = 0
125 |
126 | for j := 1; j < len(indexes); j++ {
127 | i1 := indexes[j]
128 | p := concats[i0:i1]
129 | if s == p {
130 | *v = AllSeason_Nc_Tns[j-1]
131 | return true
132 | }
133 | i0 = i1
134 | }
135 | return false
136 | }
137 |
138 | // season_nc_tnTransformInput may alter input strings before they are parsed.
139 | // This function is pluggable and is initialised using command-line flags
140 | // -ic -lc -uc -unsnake.
141 | var season_nc_tnTransformInput = func(in string) string {
142 | return in
143 | }
144 |
145 | // AsSeason_Nc_Tn parses a string to find the corresponding Season_Nc_Tn, accepting either one of the string values or
146 | // a number. The input representation is determined by season_nc_tnMarshalTextRep. It wraps Parse.
147 | func AsSeason_Nc_Tn(s string) (Season_Nc_Tn, error) {
148 | var v = new(Season_Nc_Tn)
149 | err := v.Parse(s)
150 | return *v, err
151 | }
152 |
153 | // MustParseSeason_Nc_Tn is similar to AsSeason_Nc_Tn except that it panics on error.
154 | func MustParseSeason_Nc_Tn(s string) Season_Nc_Tn {
155 | v, err := AsSeason_Nc_Tn(s)
156 | if err != nil {
157 | panic(err)
158 | }
159 | return v
160 | }
161 |
162 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
163 | func (v Season_Nc_Tn) MarshalText() ([]byte, error) {
164 | s, err := v.marshalText()
165 | return []byte(s), err
166 | }
167 |
168 | // marshalText converts values to a form suitable for transmission via XML, JSON etc.
169 | // The number representation is chosen according to -marshaltext.
170 | func (v Season_Nc_Tn) marshalText() (string, error) {
171 | if !v.IsValid() {
172 | return v.marshalNumberStringOrError()
173 | }
174 |
175 | return season_nc_tnMarshalNumber(v), nil
176 | }
177 |
178 | func (v Season_Nc_Tn) marshalNumberStringOrError() (string, error) {
179 | bs, err := v.marshalNumberOrError()
180 | return string(bs), err
181 | }
182 |
183 | func (v Season_Nc_Tn) marshalNumberOrError() ([]byte, error) {
184 | // disallow lenient marshaling
185 | return nil, v.invalidError()
186 | }
187 |
188 | func (v Season_Nc_Tn) invalidError() error {
189 | return fmt.Errorf("%d is not a valid season_nc_tn", v)
190 | }
191 |
192 | // season_nc_tnMarshalNumber handles marshaling where a number is required or where
193 | // the value is out of range.
194 | // This function can be replaced with any bespoke function than matches signature.
195 | var season_nc_tnMarshalNumber = func(v Season_Nc_Tn) string {
196 | return strconv.FormatInt(int64(v), 10)
197 | }
198 |
199 | // UnmarshalText converts transmitted values to ordinary values.
200 | func (v *Season_Nc_Tn) UnmarshalText(bs []byte) error {
201 | return v.unmarshalText(string(bs))
202 | }
203 |
204 | func (v *Season_Nc_Tn) unmarshalText(in string) error {
205 | if v.parseNumber(in) {
206 | return nil
207 | }
208 |
209 | s := season_nc_tnTransformInput(in)
210 |
211 | return v.parseFallback(in, s)
212 | }
213 |
--------------------------------------------------------------------------------
/internal/test/season_nc_tt_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | )
12 |
13 | // AllSeason_Nc_Tts lists all 4 values in order.
14 | var AllSeason_Nc_Tts = []Season_Nc_Tt{
15 | Spring_Nc_Tt, Summer_Nc_Tt, Autumn_Nc_Tt, Winter_Nc_Tt,
16 | }
17 |
18 | const (
19 | season_nc_ttEnumStrings = "SpringSummerAutumnWinter"
20 | season_nc_ttTextStrings = "SprgSumrAutmWint"
21 | )
22 |
23 | var (
24 | season_nc_ttEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | season_nc_ttTextIndex = [...]uint16{0, 4, 8, 12, 16}
26 | )
27 |
28 | // String returns the literal string representation of a Season_Nc_Tt, which is
29 | // the same as the const identifier but without prefix or suffix.
30 | func (v Season_Nc_Tt) String() string {
31 | o := v.Ordinal()
32 | return v.toString(o, season_nc_ttEnumStrings, season_nc_ttEnumIndex[:])
33 | }
34 |
35 | // Ordinal returns the ordinal number of a Season_Nc_Tt. This is an integer counting
36 | // from zero. It is *not* the same as the const number assigned to the value.
37 | func (v Season_Nc_Tt) Ordinal() int {
38 | switch v {
39 | case Spring_Nc_Tt:
40 | return 0
41 | case Summer_Nc_Tt:
42 | return 1
43 | case Autumn_Nc_Tt:
44 | return 2
45 | case Winter_Nc_Tt:
46 | return 3
47 | }
48 | return -1
49 | }
50 |
51 | func (v Season_Nc_Tt) toString(o int, concats string, indexes []uint16) string {
52 | if o < 0 || o >= len(AllSeason_Nc_Tts) {
53 | return fmt.Sprintf("Season_Nc_Tt(%d)", v)
54 | }
55 | return concats[indexes[o]:indexes[o+1]]
56 | }
57 |
58 | // IsValid determines whether a Season_Nc_Tt is one of the defined constants.
59 | func (v Season_Nc_Tt) IsValid() bool {
60 | return v.Ordinal() >= 0
61 | }
62 |
63 | // Int returns the int value, which is not necessarily the same as the ordinal.
64 | // This facilitates polymorphism (see enum.IntEnum).
65 | func (v Season_Nc_Tt) Int() int {
66 | return int(v)
67 | }
68 |
69 | var invalidSeason_Nc_TtValue = func() Season_Nc_Tt {
70 | var v Season_Nc_Tt
71 | for {
72 | if !slices.Contains(AllSeason_Nc_Tts, v) {
73 | return v
74 | }
75 | v++
76 | } // AllSeason_Nc_Tts is a finite set so loop will terminate eventually
77 | }()
78 |
79 | // Season_Nc_TtOf returns a Season_Nc_Tt based on an ordinal number. This is the inverse of Ordinal.
80 | // If the ordinal is out of range, an invalid Season_Nc_Tt is returned.
81 | func Season_Nc_TtOf(v int) Season_Nc_Tt {
82 | if 0 <= v && v < len(AllSeason_Nc_Tts) {
83 | return AllSeason_Nc_Tts[v]
84 | }
85 | return invalidSeason_Nc_TtValue
86 | }
87 |
88 | // Parse parses a string to find the corresponding Season_Nc_Tt, accepting one of the string values or
89 | // a number. It is used by AsSeason_Nc_Tt.
90 | //
91 | // Usage Example
92 | //
93 | // v := new(Season_Nc_Tt)
94 | // err := v.Parse(s)
95 | // ... etc
96 | func (v *Season_Nc_Tt) Parse(in string) error {
97 | if v.parseNumber(in) {
98 | return nil
99 | }
100 |
101 | s := season_nc_ttTransformInput(in)
102 |
103 | return v.parseFallback(in, s)
104 | }
105 |
106 | // parseNumber attempts to convert a decimal value.
107 | // Only numbers that correspond to the enumeration are valid.
108 | func (v *Season_Nc_Tt) parseNumber(s string) (ok bool) {
109 | num, err := strconv.ParseInt(s, 10, 64)
110 | if err == nil {
111 | *v = Season_Nc_Tt(num)
112 | return v.IsValid()
113 | }
114 | return false
115 | }
116 |
117 | func (v *Season_Nc_Tt) parseFallback(in, s string) error {
118 | if v.parseString(s, season_nc_ttEnumStrings, season_nc_ttEnumIndex[:]) {
119 | return nil
120 | }
121 |
122 | return errors.New(in + ": unrecognised season_nc_tt")
123 | }
124 |
125 | func (v *Season_Nc_Tt) parseString(s string, concats string, indexes []uint16) (ok bool) {
126 | var i0 uint16 = 0
127 |
128 | for j := 1; j < len(indexes); j++ {
129 | i1 := indexes[j]
130 | p := concats[i0:i1]
131 | if s == p {
132 | *v = AllSeason_Nc_Tts[j-1]
133 | return true
134 | }
135 | i0 = i1
136 | }
137 | return false
138 | }
139 |
140 | // season_nc_ttTransformInput may alter input strings before they are parsed.
141 | // This function is pluggable and is initialised using command-line flags
142 | // -ic -lc -uc -unsnake.
143 | var season_nc_ttTransformInput = func(in string) string {
144 | return in
145 | }
146 |
147 | // AsSeason_Nc_Tt parses a string to find the corresponding Season_Nc_Tt, accepting either one of the string values or
148 | // a number. It wraps Parse.
149 | func AsSeason_Nc_Tt(s string) (Season_Nc_Tt, error) {
150 | var v = new(Season_Nc_Tt)
151 | err := v.Parse(s)
152 | return *v, err
153 | }
154 |
155 | // MustParseSeason_Nc_Tt is similar to AsSeason_Nc_Tt except that it panics on error.
156 | func MustParseSeason_Nc_Tt(s string) Season_Nc_Tt {
157 | v, err := AsSeason_Nc_Tt(s)
158 | if err != nil {
159 | panic(err)
160 | }
161 | return v
162 | }
163 |
164 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
165 | func (v Season_Nc_Tt) MarshalText() ([]byte, error) {
166 | s, err := v.marshalText()
167 | return []byte(s), err
168 | }
169 |
170 | // Text returns the representation used for transmission via XML, JSON etc.
171 | func (v Season_Nc_Tt) Text() string {
172 | s, _ := v.marshalText()
173 | return s
174 | }
175 |
176 | // marshalText converts values to bytes suitable for transmission via XML, JSON etc.
177 | // The representation is chosen according to 'text' struct tags.
178 | func (v Season_Nc_Tt) marshalText() (string, error) {
179 | o := v.Ordinal()
180 | if o < 0 {
181 | return v.marshalNumberStringOrError()
182 | }
183 |
184 | return v.toString(o, season_nc_ttTextStrings, season_nc_ttTextIndex[:]), nil
185 | }
186 |
187 | func (v Season_Nc_Tt) marshalNumberStringOrError() (string, error) {
188 | bs, err := v.marshalNumberOrError()
189 | return string(bs), err
190 | }
191 |
192 | func (v Season_Nc_Tt) marshalNumberOrError() ([]byte, error) {
193 | // disallow lenient marshaling
194 | return nil, v.invalidError()
195 | }
196 |
197 | func (v Season_Nc_Tt) invalidError() error {
198 | return fmt.Errorf("%d is not a valid season_nc_tt", v)
199 | }
200 |
201 | // UnmarshalText converts transmitted values to ordinary values.
202 | func (v *Season_Nc_Tt) UnmarshalText(bs []byte) error {
203 | return v.unmarshalText(string(bs))
204 | }
205 |
206 | func (v *Season_Nc_Tt) unmarshalText(in string) error {
207 | if v.parseNumber(in) {
208 | return nil
209 | }
210 |
211 | s := season_nc_ttTransformInput(in)
212 |
213 | if v.parseString(s, season_nc_ttTextStrings, season_nc_ttTextIndex[:]) {
214 | return nil
215 | }
216 |
217 | return v.parseFallback(in, s)
218 | }
219 |
--------------------------------------------------------------------------------
/internal/test/season_sql.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Si -suffix _Nc_Si -store identifier
4 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Sn -suffix _Nc_Sn -store number
5 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Ss -suffix _Nc_Ss
6 |
7 | type (
8 | Season_Nc_Si uint
9 | Season_Nc_Sn uint
10 | Season_Nc_Ss uint
11 | )
12 |
13 | const (
14 | Spring_Nc_Si, Summer_Nc_Si, Autumn_Nc_Si, Winter_Nc_Si Season_Nc_Si = 1, 2, 3, 4
15 | )
16 |
17 | const (
18 | Spring_Nc_Sn, Summer_Nc_Sn, Autumn_Nc_Sn, Winter_Nc_Sn Season_Nc_Sn = 1, 2, 3, 4
19 | )
20 |
21 | const (
22 | _ Season_Nc_Ss = iota
23 | Spring_Nc_Ss // sql:"Sprg"
24 | Summer_Nc_Ss // sql:"Sumr"
25 | Autumn_Nc_Ss // sql:"Autm"
26 | Winter_Nc_Ss // sql:"Wint"
27 | )
28 |
29 | //=================================================================================================
30 | //go:generate enumeration -v -f -i season_sql.go -type Season_Ic_Si -suffix _Ic_Si -ic -store identifier
31 | //go:generate enumeration -v -f -i season_sql.go -type Season_Ic_Sn -suffix _Ic_Sn -ic -store number
32 | //go:generate enumeration -v -f -i season_sql.go -type Season_Ic_Ss -suffix _Ic_Ss -ic
33 |
34 | type (
35 | Season_Ic_Si uint
36 | Season_Ic_Sn uint
37 | Season_Ic_Ss uint
38 | )
39 |
40 | const (
41 | Spring_Ic_Si, Summer_Ic_Si, Autumn_Ic_Si, Winter_Ic_Si Season_Ic_Si = 1, 2, 3, 4
42 | )
43 |
44 | const (
45 | Spring_Ic_Sn, Summer_Ic_Sn, Autumn_Ic_Sn, Winter_Ic_Sn Season_Ic_Sn = 1, 2, 3, 4
46 | )
47 |
48 | const (
49 | _ Season_Ic_Ss = iota
50 | Spring_Ic_Ss // sql:"Sprg"
51 | Summer_Ic_Ss // sql:"Sumr"
52 | Autumn_Ic_Ss // sql:"Autm"
53 | Winter_Ic_Ss // sql:"Wint"
54 | )
55 |
56 | //=================================================================================================
57 | //go:generate enumeration -v -f -i season_sql.go -type Season_Uc_Si -suffix _Uc_Si -uc -store identifier
58 | //go:generate enumeration -v -f -i season_sql.go -type Season_Uc_Sn -suffix _Uc_Sn -uc -store number
59 |
60 | type (
61 | Season_Uc_Si uint
62 | Season_Uc_Sn uint
63 | )
64 |
65 | const (
66 | Spring_Uc_Si, Summer_Uc_Si, Autumn_Uc_Si, Winter_Uc_Si Season_Uc_Si = 1, 2, 3, 4
67 | )
68 |
69 | const (
70 | Spring_Uc_Sn, Summer_Uc_Sn, Autumn_Uc_Sn, Winter_Uc_Sn Season_Uc_Sn = 1, 2, 3, 4
71 | )
72 |
--------------------------------------------------------------------------------
/internal/test/season_text.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | //=================================================================================================
4 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Ti -suffix _Nc_Ti -marshaltext identifier
5 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Tn -suffix _Nc_Tn -marshaltext number
6 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Tt -suffix _Nc_Tt
7 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Ta -suffix _Nc_Ta
8 |
9 | type (
10 | Season_Nc_Ti uint
11 | Season_Nc_Tn uint
12 | Season_Nc_Tt uint
13 | Season_Nc_Ta uint
14 | )
15 |
16 | const (
17 | Spring_Nc_Ti, Summer_Nc_Ti, Autumn_Nc_Ti, Winter_Nc_Ti Season_Nc_Ti = 1, 2, 3, 4
18 | )
19 |
20 | const (
21 | Spring_Nc_Tn, Summer_Nc_Tn, Autumn_Nc_Tn, Winter_Nc_Tn Season_Nc_Tn = 1, 2, 3, 4
22 | )
23 |
24 | const (
25 | _ Season_Nc_Tt = iota
26 | Spring_Nc_Tt // text:"Sprg"
27 | Summer_Nc_Tt // text:"Sumr"
28 | Autumn_Nc_Tt // text:"Autm"
29 | Winter_Nc_Tt // text:"Wint"
30 | )
31 |
32 | const (
33 | _ Season_Nc_Ta = iota
34 | Spring_Nc_Ta // all:"Sprg"
35 | Summer_Nc_Ta // all:"Sumr"
36 | Autumn_Nc_Ta // all:"Autm"
37 | Winter_Nc_Ta // all:"Wint"
38 | )
39 |
40 | //=================================================================================================
41 | //go:generate enumeration -v -f -i season_text.go -type Season_Ic_Ti -suffix _Ic_Ti -ic -marshaltext identifier
42 | //go:generate enumeration -v -f -i season_text.go -type Season_Ic_Tn -suffix _Ic_Tn -ic -marshaltext number
43 | //go:generate enumeration -v -f -i season_text.go -type Season_Ic_Tt -suffix _Ic_Tt -ic
44 | //go:generate enumeration -v -f -i season_text.go -type Season_Ic_Ta -suffix _Ic_Ta -ic
45 |
46 | type (
47 | Season_Ic_Ti uint
48 | Season_Ic_Tn uint
49 | Season_Ic_Tt uint
50 | Season_Ic_Ta uint
51 | )
52 |
53 | const (
54 | Spring_Ic_Ti, Summer_Ic_Ti, Autumn_Ic_Ti, Winter_Ic_Ti Season_Ic_Ti = 1, 2, 3, 4
55 | )
56 |
57 | const (
58 | Spring_Ic_Tn, Summer_Ic_Tn, Autumn_Ic_Tn, Winter_Ic_Tn Season_Ic_Tn = 1, 2, 3, 4
59 | )
60 |
61 | const (
62 | _ Season_Ic_Tt = iota
63 | Spring_Ic_Tt // text:"Sprg"
64 | Summer_Ic_Tt // text:"Sumr"
65 | Autumn_Ic_Tt // text:"Autm"
66 | Winter_Ic_Tt // text:"Wint"
67 | )
68 |
69 | const (
70 | _ Season_Ic_Ta = iota
71 | Spring_Ic_Ta // all:"Sprg"
72 | Summer_Ic_Ta // all:"Sumr"
73 | Autumn_Ic_Ta // all:"Autm"
74 | Winter_Ic_Ta // all:"Wint"
75 | )
76 |
77 | //=================================================================================================
78 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Ti -suffix _Uc_Ti -uc -marshaltext identifier
79 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Tn -suffix _Uc_Tn -uc -marshaltext number
80 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Tt -suffix _Uc_Tt -uc
81 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Ta -suffix _Uc_Ta -uc
82 |
83 | type (
84 | Season_Uc_Ti uint
85 | Season_Uc_Tn uint
86 | Season_Uc_Tt uint
87 | Season_Uc_Ta uint
88 | )
89 |
90 | const (
91 | Spring_Uc_Ti, Summer_Uc_Ti, Autumn_Uc_Ti, Winter_Uc_Ti Season_Uc_Ti = 1, 2, 3, 4
92 | )
93 |
94 | const (
95 | Spring_Uc_Tn, Summer_Uc_Tn, Autumn_Uc_Tn, Winter_Uc_Tn Season_Uc_Tn = 1, 2, 3, 4
96 | )
97 |
98 | const (
99 | _ Season_Uc_Tt = iota
100 | Spring_Uc_Tt // text:"Sprg"
101 | Summer_Uc_Tt // text:"Sumr"
102 | Autumn_Uc_Tt // text:"Autm"
103 | Winter_Uc_Tt // text:"Wint"
104 | )
105 |
106 | const (
107 | _ Season_Uc_Ta = iota
108 | Spring_Uc_Ta // all:"Sprg"
109 | Summer_Uc_Ta // all:"Sumr"
110 | Autumn_Uc_Ta // all:"Autm"
111 | Winter_Uc_Ta // all:"Wint"
112 | )
113 |
--------------------------------------------------------------------------------
/internal/test/season_uc_jn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Uc_Jns lists all 4 values in order.
15 | var AllSeason_Uc_Jns = []Season_Uc_Jn{
16 | Spring_Uc_Jn, Summer_Uc_Jn, Autumn_Uc_Jn, Winter_Uc_Jn,
17 | }
18 |
19 | const (
20 | season_uc_jnEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
21 | )
22 |
23 | var (
24 | season_uc_jnEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Uc_Jn, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Uc_Jn) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_uc_jnEnumStrings, season_uc_jnEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Uc_Jn. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Uc_Jn) Ordinal() int {
37 | switch v {
38 | case Spring_Uc_Jn:
39 | return 0
40 | case Summer_Uc_Jn:
41 | return 1
42 | case Autumn_Uc_Jn:
43 | return 2
44 | case Winter_Uc_Jn:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Uc_Jn) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Uc_Jns) {
52 | return fmt.Sprintf("Season_Uc_Jn(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Uc_Jn is one of the defined constants.
58 | func (v Season_Uc_Jn) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Uc_Jn) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Uc_JnValue = func() Season_Uc_Jn {
69 | var v Season_Uc_Jn
70 | for {
71 | if !slices.Contains(AllSeason_Uc_Jns, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Uc_Jns is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Uc_JnOf returns a Season_Uc_Jn based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Uc_Jn is returned.
80 | func Season_Uc_JnOf(v int) Season_Uc_Jn {
81 | if 0 <= v && v < len(AllSeason_Uc_Jns) {
82 | return AllSeason_Uc_Jns[v]
83 | }
84 | return invalidSeason_Uc_JnValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Uc_Jn, accepting one of the string values or
88 | // a number. It is used by AsSeason_Uc_Jn.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Uc_Jn)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Uc_Jn) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_uc_jnTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Uc_Jn) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Uc_Jn(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Uc_Jn) parseFallback(in, s string) error {
117 | if v.parseString(s, season_uc_jnEnumStrings, season_uc_jnEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_uc_jn")
122 | }
123 |
124 | func (v *Season_Uc_Jn) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Uc_Jns[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_uc_jnTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_uc_jnTransformInput = func(in string) string {
143 | return strings.ToUpper(in)
144 | }
145 |
146 | // AsSeason_Uc_Jn parses a string to find the corresponding Season_Uc_Jn, accepting either one of the string values or
147 | // a number. It wraps Parse.
148 | func AsSeason_Uc_Jn(s string) (Season_Uc_Jn, error) {
149 | var v = new(Season_Uc_Jn)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Uc_Jn is similar to AsSeason_Uc_Jn except that it panics on error.
155 | func MustParseSeason_Uc_Jn(s string) Season_Uc_Jn {
156 | v, err := AsSeason_Uc_Jn(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // MarshalJSON converts values to bytes suitable for transmission via JSON.
164 | // The number representation is chosen according to -marshaljson.
165 | func (v Season_Uc_Jn) MarshalJSON() ([]byte, error) {
166 | if !v.IsValid() {
167 | return v.marshalNumberOrError()
168 | }
169 |
170 | s := season_uc_jnMarshalNumber(v)
171 | return []byte(s), nil
172 | }
173 |
174 | func (v Season_Uc_Jn) marshalNumberOrError() ([]byte, error) {
175 | // disallow lenient marshaling
176 | return nil, v.invalidError()
177 | }
178 |
179 | func (v Season_Uc_Jn) invalidError() error {
180 | return fmt.Errorf("%d is not a valid season_uc_jn", v)
181 | }
182 |
183 | // season_uc_jnMarshalNumber handles marshaling where a number is required or where
184 | // the value is out of range.
185 | // This function can be replaced with any bespoke function than matches signature.
186 | var season_uc_jnMarshalNumber = func(v Season_Uc_Jn) string {
187 | return strconv.FormatInt(int64(v), 10)
188 | }
189 |
190 | // UnmarshalJSON converts transmitted JSON values to ordinary values. It allows both
191 | // ordinals and strings to represent the values.
192 | func (v *Season_Uc_Jn) UnmarshalJSON(text []byte) error {
193 | s := string(text)
194 | if s == "null" {
195 | // Ignore null, like in the main JSON package.
196 | return nil
197 | }
198 | s = strings.Trim(s, "\"")
199 | return v.unmarshalJSON(s)
200 | }
201 |
202 | func (v *Season_Uc_Jn) unmarshalJSON(in string) error {
203 | if v.parseNumber(in) {
204 | return nil
205 | }
206 |
207 | s := season_uc_jnTransformInput(in)
208 |
209 | if v.parseString(s, season_uc_jnEnumStrings, season_uc_jnEnumIndex[:]) {
210 | return nil
211 | }
212 |
213 | return errors.New(in + ": unrecognised season_uc_jn")
214 | }
215 |
--------------------------------------------------------------------------------
/internal/test/season_uc_si_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | // AllSeason_Uc_Sis lists all 4 values in order.
16 | var AllSeason_Uc_Sis = []Season_Uc_Si{
17 | Spring_Uc_Si, Summer_Uc_Si, Autumn_Uc_Si, Winter_Uc_Si,
18 | }
19 |
20 | const (
21 | season_uc_siEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
22 | )
23 |
24 | var (
25 | season_uc_siEnumIndex = [...]uint16{0, 6, 12, 18, 24}
26 | )
27 |
28 | // String returns the literal string representation of a Season_Uc_Si, which is
29 | // the same as the const identifier but without prefix or suffix.
30 | func (v Season_Uc_Si) String() string {
31 | o := v.Ordinal()
32 | return v.toString(o, season_uc_siEnumStrings, season_uc_siEnumIndex[:])
33 | }
34 |
35 | // Ordinal returns the ordinal number of a Season_Uc_Si. This is an integer counting
36 | // from zero. It is *not* the same as the const number assigned to the value.
37 | func (v Season_Uc_Si) Ordinal() int {
38 | switch v {
39 | case Spring_Uc_Si:
40 | return 0
41 | case Summer_Uc_Si:
42 | return 1
43 | case Autumn_Uc_Si:
44 | return 2
45 | case Winter_Uc_Si:
46 | return 3
47 | }
48 | return -1
49 | }
50 |
51 | func (v Season_Uc_Si) toString(o int, concats string, indexes []uint16) string {
52 | if o < 0 || o >= len(AllSeason_Uc_Sis) {
53 | return fmt.Sprintf("Season_Uc_Si(%d)", v)
54 | }
55 | return concats[indexes[o]:indexes[o+1]]
56 | }
57 |
58 | // IsValid determines whether a Season_Uc_Si is one of the defined constants.
59 | func (v Season_Uc_Si) IsValid() bool {
60 | return v.Ordinal() >= 0
61 | }
62 |
63 | // Int returns the int value, which is not necessarily the same as the ordinal.
64 | // This facilitates polymorphism (see enum.IntEnum).
65 | func (v Season_Uc_Si) Int() int {
66 | return int(v)
67 | }
68 |
69 | var invalidSeason_Uc_SiValue = func() Season_Uc_Si {
70 | var v Season_Uc_Si
71 | for {
72 | if !slices.Contains(AllSeason_Uc_Sis, v) {
73 | return v
74 | }
75 | v++
76 | } // AllSeason_Uc_Sis is a finite set so loop will terminate eventually
77 | }()
78 |
79 | // Season_Uc_SiOf returns a Season_Uc_Si based on an ordinal number. This is the inverse of Ordinal.
80 | // If the ordinal is out of range, an invalid Season_Uc_Si is returned.
81 | func Season_Uc_SiOf(v int) Season_Uc_Si {
82 | if 0 <= v && v < len(AllSeason_Uc_Sis) {
83 | return AllSeason_Uc_Sis[v]
84 | }
85 | return invalidSeason_Uc_SiValue
86 | }
87 |
88 | // Parse parses a string to find the corresponding Season_Uc_Si, accepting one of the string values or
89 | // a number. It is used by AsSeason_Uc_Si.
90 | //
91 | // Usage Example
92 | //
93 | // v := new(Season_Uc_Si)
94 | // err := v.Parse(s)
95 | // ... etc
96 | func (v *Season_Uc_Si) Parse(in string) error {
97 | if v.parseNumber(in) {
98 | return nil
99 | }
100 |
101 | s := season_uc_siTransformInput(in)
102 |
103 | return v.parseFallback(in, s)
104 | }
105 |
106 | // parseNumber attempts to convert a decimal value.
107 | // Only numbers that correspond to the enumeration are valid.
108 | func (v *Season_Uc_Si) parseNumber(s string) (ok bool) {
109 | num, err := strconv.ParseInt(s, 10, 64)
110 | if err == nil {
111 | *v = Season_Uc_Si(num)
112 | return v.IsValid()
113 | }
114 | return false
115 | }
116 |
117 | func (v *Season_Uc_Si) parseFallback(in, s string) error {
118 | if v.parseString(s, season_uc_siEnumStrings, season_uc_siEnumIndex[:]) {
119 | return nil
120 | }
121 |
122 | return errors.New(in + ": unrecognised season_uc_si")
123 | }
124 |
125 | func (v *Season_Uc_Si) parseString(s string, concats string, indexes []uint16) (ok bool) {
126 | var i0 uint16 = 0
127 |
128 | for j := 1; j < len(indexes); j++ {
129 | i1 := indexes[j]
130 | p := concats[i0:i1]
131 | if s == p {
132 | *v = AllSeason_Uc_Sis[j-1]
133 | return true
134 | }
135 | i0 = i1
136 | }
137 | return false
138 | }
139 |
140 | // season_uc_siTransformInput may alter input strings before they are parsed.
141 | // This function is pluggable and is initialised using command-line flags
142 | // -ic -lc -uc -unsnake.
143 | var season_uc_siTransformInput = func(in string) string {
144 | return strings.ToUpper(in)
145 | }
146 |
147 | // AsSeason_Uc_Si parses a string to find the corresponding Season_Uc_Si, accepting either one of the string values or
148 | // a number. It wraps Parse.
149 | func AsSeason_Uc_Si(s string) (Season_Uc_Si, error) {
150 | var v = new(Season_Uc_Si)
151 | err := v.Parse(s)
152 | return *v, err
153 | }
154 |
155 | // MustParseSeason_Uc_Si is similar to AsSeason_Uc_Si except that it panics on error.
156 | func MustParseSeason_Uc_Si(s string) Season_Uc_Si {
157 | v, err := AsSeason_Uc_Si(s)
158 | if err != nil {
159 | panic(err)
160 | }
161 | return v
162 | }
163 |
164 | // Scan parses some value, which can be a number, a string or []byte.
165 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
166 | func (v *Season_Uc_Si) Scan(value interface{}) error {
167 | if value == nil {
168 | return nil
169 | }
170 |
171 | var s string
172 | switch x := value.(type) {
173 | case int64:
174 | *v = Season_Uc_Si(x)
175 | return v.errorIfInvalid()
176 | case float64:
177 | *v = Season_Uc_Si(x)
178 | return v.errorIfInvalid()
179 | case []byte:
180 | s = string(x)
181 | case string:
182 | s = x
183 | default:
184 | return fmt.Errorf("%T %+v is not a meaningful season_uc_si", value, value)
185 | }
186 |
187 | return v.scanParse(s)
188 | }
189 |
190 | func (v Season_Uc_Si) errorIfInvalid() error {
191 | if v.IsValid() {
192 | return nil
193 | }
194 | return v.invalidError()
195 | }
196 |
197 | func (v Season_Uc_Si) invalidError() error {
198 | return fmt.Errorf("%d is not a valid season_uc_si", v)
199 | }
200 |
201 | func (v *Season_Uc_Si) scanParse(in string) error {
202 | if v.parseNumber(in) {
203 | return nil
204 | }
205 |
206 | s := season_uc_siTransformInput(in)
207 |
208 | return v.parseFallback(in, s)
209 | }
210 |
211 | // Value converts the Season_Uc_Si to a string (based on '-store identifier').
212 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
213 | func (v Season_Uc_Si) Value() (driver.Value, error) {
214 | if !v.IsValid() {
215 | return nil, fmt.Errorf("%v: cannot be stored", v)
216 | }
217 |
218 | return v.String(), nil
219 | }
220 |
--------------------------------------------------------------------------------
/internal/test/season_uc_sn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "database/sql/driver"
8 | "errors"
9 | "fmt"
10 | "slices"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | // AllSeason_Uc_Sns lists all 4 values in order.
16 | var AllSeason_Uc_Sns = []Season_Uc_Sn{
17 | Spring_Uc_Sn, Summer_Uc_Sn, Autumn_Uc_Sn, Winter_Uc_Sn,
18 | }
19 |
20 | const (
21 | season_uc_snEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
22 | )
23 |
24 | var (
25 | season_uc_snEnumIndex = [...]uint16{0, 6, 12, 18, 24}
26 | )
27 |
28 | // String returns the literal string representation of a Season_Uc_Sn, which is
29 | // the same as the const identifier but without prefix or suffix.
30 | func (v Season_Uc_Sn) String() string {
31 | o := v.Ordinal()
32 | return v.toString(o, season_uc_snEnumStrings, season_uc_snEnumIndex[:])
33 | }
34 |
35 | // Ordinal returns the ordinal number of a Season_Uc_Sn. This is an integer counting
36 | // from zero. It is *not* the same as the const number assigned to the value.
37 | func (v Season_Uc_Sn) Ordinal() int {
38 | switch v {
39 | case Spring_Uc_Sn:
40 | return 0
41 | case Summer_Uc_Sn:
42 | return 1
43 | case Autumn_Uc_Sn:
44 | return 2
45 | case Winter_Uc_Sn:
46 | return 3
47 | }
48 | return -1
49 | }
50 |
51 | func (v Season_Uc_Sn) toString(o int, concats string, indexes []uint16) string {
52 | if o < 0 || o >= len(AllSeason_Uc_Sns) {
53 | return fmt.Sprintf("Season_Uc_Sn(%d)", v)
54 | }
55 | return concats[indexes[o]:indexes[o+1]]
56 | }
57 |
58 | // IsValid determines whether a Season_Uc_Sn is one of the defined constants.
59 | func (v Season_Uc_Sn) IsValid() bool {
60 | return v.Ordinal() >= 0
61 | }
62 |
63 | // Int returns the int value, which is not necessarily the same as the ordinal.
64 | // This facilitates polymorphism (see enum.IntEnum).
65 | func (v Season_Uc_Sn) Int() int {
66 | return int(v)
67 | }
68 |
69 | var invalidSeason_Uc_SnValue = func() Season_Uc_Sn {
70 | var v Season_Uc_Sn
71 | for {
72 | if !slices.Contains(AllSeason_Uc_Sns, v) {
73 | return v
74 | }
75 | v++
76 | } // AllSeason_Uc_Sns is a finite set so loop will terminate eventually
77 | }()
78 |
79 | // Season_Uc_SnOf returns a Season_Uc_Sn based on an ordinal number. This is the inverse of Ordinal.
80 | // If the ordinal is out of range, an invalid Season_Uc_Sn is returned.
81 | func Season_Uc_SnOf(v int) Season_Uc_Sn {
82 | if 0 <= v && v < len(AllSeason_Uc_Sns) {
83 | return AllSeason_Uc_Sns[v]
84 | }
85 | return invalidSeason_Uc_SnValue
86 | }
87 |
88 | // Parse parses a string to find the corresponding Season_Uc_Sn, accepting one of the string values or
89 | // a number. It is used by AsSeason_Uc_Sn.
90 | //
91 | // Usage Example
92 | //
93 | // v := new(Season_Uc_Sn)
94 | // err := v.Parse(s)
95 | // ... etc
96 | func (v *Season_Uc_Sn) Parse(in string) error {
97 | if v.parseNumber(in) {
98 | return nil
99 | }
100 |
101 | s := season_uc_snTransformInput(in)
102 |
103 | return v.parseFallback(in, s)
104 | }
105 |
106 | // parseNumber attempts to convert a decimal value.
107 | // Only numbers that correspond to the enumeration are valid.
108 | func (v *Season_Uc_Sn) parseNumber(s string) (ok bool) {
109 | num, err := strconv.ParseInt(s, 10, 64)
110 | if err == nil {
111 | *v = Season_Uc_Sn(num)
112 | return v.IsValid()
113 | }
114 | return false
115 | }
116 |
117 | func (v *Season_Uc_Sn) parseFallback(in, s string) error {
118 | if v.parseString(s, season_uc_snEnumStrings, season_uc_snEnumIndex[:]) {
119 | return nil
120 | }
121 |
122 | return errors.New(in + ": unrecognised season_uc_sn")
123 | }
124 |
125 | func (v *Season_Uc_Sn) parseString(s string, concats string, indexes []uint16) (ok bool) {
126 | var i0 uint16 = 0
127 |
128 | for j := 1; j < len(indexes); j++ {
129 | i1 := indexes[j]
130 | p := concats[i0:i1]
131 | if s == p {
132 | *v = AllSeason_Uc_Sns[j-1]
133 | return true
134 | }
135 | i0 = i1
136 | }
137 | return false
138 | }
139 |
140 | // season_uc_snTransformInput may alter input strings before they are parsed.
141 | // This function is pluggable and is initialised using command-line flags
142 | // -ic -lc -uc -unsnake.
143 | var season_uc_snTransformInput = func(in string) string {
144 | return strings.ToUpper(in)
145 | }
146 |
147 | // AsSeason_Uc_Sn parses a string to find the corresponding Season_Uc_Sn, accepting either one of the string values or
148 | // a number. It wraps Parse.
149 | func AsSeason_Uc_Sn(s string) (Season_Uc_Sn, error) {
150 | var v = new(Season_Uc_Sn)
151 | err := v.Parse(s)
152 | return *v, err
153 | }
154 |
155 | // MustParseSeason_Uc_Sn is similar to AsSeason_Uc_Sn except that it panics on error.
156 | func MustParseSeason_Uc_Sn(s string) Season_Uc_Sn {
157 | v, err := AsSeason_Uc_Sn(s)
158 | if err != nil {
159 | panic(err)
160 | }
161 | return v
162 | }
163 |
164 | // Scan parses some value, which can be a number, a string or []byte.
165 | // It implements sql.Scanner, https://golang.org/pkg/database/sql/#Scanner
166 | func (v *Season_Uc_Sn) Scan(value interface{}) error {
167 | if value == nil {
168 | return nil
169 | }
170 |
171 | var s string
172 | switch x := value.(type) {
173 | case int64:
174 | *v = Season_Uc_Sn(x)
175 | return v.errorIfInvalid()
176 | case float64:
177 | *v = Season_Uc_Sn(x)
178 | return v.errorIfInvalid()
179 | case []byte:
180 | s = string(x)
181 | case string:
182 | s = x
183 | default:
184 | return fmt.Errorf("%T %+v is not a meaningful season_uc_sn", value, value)
185 | }
186 |
187 | return v.scanParse(s)
188 | }
189 |
190 | func (v Season_Uc_Sn) errorIfInvalid() error {
191 | if v.IsValid() {
192 | return nil
193 | }
194 | return v.invalidError()
195 | }
196 |
197 | func (v Season_Uc_Sn) invalidError() error {
198 | return fmt.Errorf("%d is not a valid season_uc_sn", v)
199 | }
200 |
201 | func (v *Season_Uc_Sn) scanParse(in string) error {
202 | if v.parseNumber(in) {
203 | return nil
204 | }
205 |
206 | s := season_uc_snTransformInput(in)
207 |
208 | return v.parseFallback(in, s)
209 | }
210 |
211 | // Value converts the Season_Uc_Sn to a number (based on '-store number').
212 | // It implements driver.Valuer, https://golang.org/pkg/database/sql/driver/#Valuer
213 | func (v Season_Uc_Sn) Value() (driver.Value, error) {
214 | return int64(v), nil
215 | }
216 |
--------------------------------------------------------------------------------
/internal/test/season_uc_ti_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Uc_Tis lists all 4 values in order.
15 | var AllSeason_Uc_Tis = []Season_Uc_Ti{
16 | Spring_Uc_Ti, Summer_Uc_Ti, Autumn_Uc_Ti, Winter_Uc_Ti,
17 | }
18 |
19 | const (
20 | season_uc_tiEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
21 | )
22 |
23 | var (
24 | season_uc_tiEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Uc_Ti, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Uc_Ti) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_uc_tiEnumStrings, season_uc_tiEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Uc_Ti. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Uc_Ti) Ordinal() int {
37 | switch v {
38 | case Spring_Uc_Ti:
39 | return 0
40 | case Summer_Uc_Ti:
41 | return 1
42 | case Autumn_Uc_Ti:
43 | return 2
44 | case Winter_Uc_Ti:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Uc_Ti) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Uc_Tis) {
52 | return fmt.Sprintf("Season_Uc_Ti(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Uc_Ti is one of the defined constants.
58 | func (v Season_Uc_Ti) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Uc_Ti) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Uc_TiValue = func() Season_Uc_Ti {
69 | var v Season_Uc_Ti
70 | for {
71 | if !slices.Contains(AllSeason_Uc_Tis, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Uc_Tis is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Uc_TiOf returns a Season_Uc_Ti based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Uc_Ti is returned.
80 | func Season_Uc_TiOf(v int) Season_Uc_Ti {
81 | if 0 <= v && v < len(AllSeason_Uc_Tis) {
82 | return AllSeason_Uc_Tis[v]
83 | }
84 | return invalidSeason_Uc_TiValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Uc_Ti, accepting one of the string values or
88 | // a number. The input representation is determined by Identifier. It is used by AsSeason_Uc_Ti.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Uc_Ti)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Uc_Ti) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_uc_tiTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Uc_Ti) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Uc_Ti(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Uc_Ti) parseFallback(in, s string) error {
117 | if v.parseString(s, season_uc_tiEnumStrings, season_uc_tiEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_uc_ti")
122 | }
123 |
124 | func (v *Season_Uc_Ti) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Uc_Tis[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_uc_tiTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_uc_tiTransformInput = func(in string) string {
143 | return strings.ToUpper(in)
144 | }
145 |
146 | // AsSeason_Uc_Ti parses a string to find the corresponding Season_Uc_Ti, accepting either one of the string values or
147 | // a number. The input representation is determined by season_uc_tiMarshalTextRep. It wraps Parse.
148 | func AsSeason_Uc_Ti(s string) (Season_Uc_Ti, error) {
149 | var v = new(Season_Uc_Ti)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Uc_Ti is similar to AsSeason_Uc_Ti except that it panics on error.
155 | func MustParseSeason_Uc_Ti(s string) Season_Uc_Ti {
156 | v, err := AsSeason_Uc_Ti(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
164 | func (v Season_Uc_Ti) MarshalText() ([]byte, error) {
165 | s, err := v.marshalText()
166 | return []byte(s), err
167 | }
168 |
169 | // Text returns the representation used for transmission via XML, JSON etc.
170 | func (v Season_Uc_Ti) Text() string {
171 | s, _ := v.marshalText()
172 | return s
173 | }
174 |
175 | // marshalText converts values to a form suitable for transmission via XML, JSON etc.
176 | // The identifier representation is chosen according to -marshaltext.
177 | func (v Season_Uc_Ti) marshalText() (string, error) {
178 | o := v.Ordinal()
179 | if o < 0 {
180 | return v.marshalNumberStringOrError()
181 | }
182 |
183 | return v.toString(o, season_uc_tiEnumStrings, season_uc_tiEnumIndex[:]), nil
184 | }
185 |
186 | func (v Season_Uc_Ti) marshalNumberStringOrError() (string, error) {
187 | bs, err := v.marshalNumberOrError()
188 | return string(bs), err
189 | }
190 |
191 | func (v Season_Uc_Ti) marshalNumberOrError() ([]byte, error) {
192 | // disallow lenient marshaling
193 | return nil, v.invalidError()
194 | }
195 |
196 | func (v Season_Uc_Ti) invalidError() error {
197 | return fmt.Errorf("%d is not a valid season_uc_ti", v)
198 | }
199 |
200 | // UnmarshalText converts transmitted values to ordinary values.
201 | func (v *Season_Uc_Ti) UnmarshalText(bs []byte) error {
202 | return v.unmarshalText(string(bs))
203 | }
204 |
205 | func (v *Season_Uc_Ti) unmarshalText(in string) error {
206 | if v.parseNumber(in) {
207 | return nil
208 | }
209 |
210 | s := season_uc_tiTransformInput(in)
211 |
212 | return v.parseFallback(in, s)
213 | }
214 |
--------------------------------------------------------------------------------
/internal/test/season_uc_tn_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Uc_Tns lists all 4 values in order.
15 | var AllSeason_Uc_Tns = []Season_Uc_Tn{
16 | Spring_Uc_Tn, Summer_Uc_Tn, Autumn_Uc_Tn, Winter_Uc_Tn,
17 | }
18 |
19 | const (
20 | season_uc_tnEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
21 | )
22 |
23 | var (
24 | season_uc_tnEnumIndex = [...]uint16{0, 6, 12, 18, 24}
25 | )
26 |
27 | // String returns the literal string representation of a Season_Uc_Tn, which is
28 | // the same as the const identifier but without prefix or suffix.
29 | func (v Season_Uc_Tn) String() string {
30 | o := v.Ordinal()
31 | return v.toString(o, season_uc_tnEnumStrings, season_uc_tnEnumIndex[:])
32 | }
33 |
34 | // Ordinal returns the ordinal number of a Season_Uc_Tn. This is an integer counting
35 | // from zero. It is *not* the same as the const number assigned to the value.
36 | func (v Season_Uc_Tn) Ordinal() int {
37 | switch v {
38 | case Spring_Uc_Tn:
39 | return 0
40 | case Summer_Uc_Tn:
41 | return 1
42 | case Autumn_Uc_Tn:
43 | return 2
44 | case Winter_Uc_Tn:
45 | return 3
46 | }
47 | return -1
48 | }
49 |
50 | func (v Season_Uc_Tn) toString(o int, concats string, indexes []uint16) string {
51 | if o < 0 || o >= len(AllSeason_Uc_Tns) {
52 | return fmt.Sprintf("Season_Uc_Tn(%d)", v)
53 | }
54 | return concats[indexes[o]:indexes[o+1]]
55 | }
56 |
57 | // IsValid determines whether a Season_Uc_Tn is one of the defined constants.
58 | func (v Season_Uc_Tn) IsValid() bool {
59 | return v.Ordinal() >= 0
60 | }
61 |
62 | // Int returns the int value, which is not necessarily the same as the ordinal.
63 | // This facilitates polymorphism (see enum.IntEnum).
64 | func (v Season_Uc_Tn) Int() int {
65 | return int(v)
66 | }
67 |
68 | var invalidSeason_Uc_TnValue = func() Season_Uc_Tn {
69 | var v Season_Uc_Tn
70 | for {
71 | if !slices.Contains(AllSeason_Uc_Tns, v) {
72 | return v
73 | }
74 | v++
75 | } // AllSeason_Uc_Tns is a finite set so loop will terminate eventually
76 | }()
77 |
78 | // Season_Uc_TnOf returns a Season_Uc_Tn based on an ordinal number. This is the inverse of Ordinal.
79 | // If the ordinal is out of range, an invalid Season_Uc_Tn is returned.
80 | func Season_Uc_TnOf(v int) Season_Uc_Tn {
81 | if 0 <= v && v < len(AllSeason_Uc_Tns) {
82 | return AllSeason_Uc_Tns[v]
83 | }
84 | return invalidSeason_Uc_TnValue
85 | }
86 |
87 | // Parse parses a string to find the corresponding Season_Uc_Tn, accepting one of the string values or
88 | // a number. The input representation is determined by Number. It is used by AsSeason_Uc_Tn.
89 | //
90 | // Usage Example
91 | //
92 | // v := new(Season_Uc_Tn)
93 | // err := v.Parse(s)
94 | // ... etc
95 | func (v *Season_Uc_Tn) Parse(in string) error {
96 | if v.parseNumber(in) {
97 | return nil
98 | }
99 |
100 | s := season_uc_tnTransformInput(in)
101 |
102 | return v.parseFallback(in, s)
103 | }
104 |
105 | // parseNumber attempts to convert a decimal value.
106 | // Only numbers that correspond to the enumeration are valid.
107 | func (v *Season_Uc_Tn) parseNumber(s string) (ok bool) {
108 | num, err := strconv.ParseInt(s, 10, 64)
109 | if err == nil {
110 | *v = Season_Uc_Tn(num)
111 | return v.IsValid()
112 | }
113 | return false
114 | }
115 |
116 | func (v *Season_Uc_Tn) parseFallback(in, s string) error {
117 | if v.parseString(s, season_uc_tnEnumStrings, season_uc_tnEnumIndex[:]) {
118 | return nil
119 | }
120 |
121 | return errors.New(in + ": unrecognised season_uc_tn")
122 | }
123 |
124 | func (v *Season_Uc_Tn) parseString(s string, concats string, indexes []uint16) (ok bool) {
125 | var i0 uint16 = 0
126 |
127 | for j := 1; j < len(indexes); j++ {
128 | i1 := indexes[j]
129 | p := concats[i0:i1]
130 | if s == p {
131 | *v = AllSeason_Uc_Tns[j-1]
132 | return true
133 | }
134 | i0 = i1
135 | }
136 | return false
137 | }
138 |
139 | // season_uc_tnTransformInput may alter input strings before they are parsed.
140 | // This function is pluggable and is initialised using command-line flags
141 | // -ic -lc -uc -unsnake.
142 | var season_uc_tnTransformInput = func(in string) string {
143 | return strings.ToUpper(in)
144 | }
145 |
146 | // AsSeason_Uc_Tn parses a string to find the corresponding Season_Uc_Tn, accepting either one of the string values or
147 | // a number. The input representation is determined by season_uc_tnMarshalTextRep. It wraps Parse.
148 | func AsSeason_Uc_Tn(s string) (Season_Uc_Tn, error) {
149 | var v = new(Season_Uc_Tn)
150 | err := v.Parse(s)
151 | return *v, err
152 | }
153 |
154 | // MustParseSeason_Uc_Tn is similar to AsSeason_Uc_Tn except that it panics on error.
155 | func MustParseSeason_Uc_Tn(s string) Season_Uc_Tn {
156 | v, err := AsSeason_Uc_Tn(s)
157 | if err != nil {
158 | panic(err)
159 | }
160 | return v
161 | }
162 |
163 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
164 | func (v Season_Uc_Tn) MarshalText() ([]byte, error) {
165 | s, err := v.marshalText()
166 | return []byte(s), err
167 | }
168 |
169 | // marshalText converts values to a form suitable for transmission via XML, JSON etc.
170 | // The number representation is chosen according to -marshaltext.
171 | func (v Season_Uc_Tn) marshalText() (string, error) {
172 | if !v.IsValid() {
173 | return v.marshalNumberStringOrError()
174 | }
175 |
176 | return season_uc_tnMarshalNumber(v), nil
177 | }
178 |
179 | func (v Season_Uc_Tn) marshalNumberStringOrError() (string, error) {
180 | bs, err := v.marshalNumberOrError()
181 | return string(bs), err
182 | }
183 |
184 | func (v Season_Uc_Tn) marshalNumberOrError() ([]byte, error) {
185 | // disallow lenient marshaling
186 | return nil, v.invalidError()
187 | }
188 |
189 | func (v Season_Uc_Tn) invalidError() error {
190 | return fmt.Errorf("%d is not a valid season_uc_tn", v)
191 | }
192 |
193 | // season_uc_tnMarshalNumber handles marshaling where a number is required or where
194 | // the value is out of range.
195 | // This function can be replaced with any bespoke function than matches signature.
196 | var season_uc_tnMarshalNumber = func(v Season_Uc_Tn) string {
197 | return strconv.FormatInt(int64(v), 10)
198 | }
199 |
200 | // UnmarshalText converts transmitted values to ordinary values.
201 | func (v *Season_Uc_Tn) UnmarshalText(bs []byte) error {
202 | return v.unmarshalText(string(bs))
203 | }
204 |
205 | func (v *Season_Uc_Tn) unmarshalText(in string) error {
206 | if v.parseNumber(in) {
207 | return nil
208 | }
209 |
210 | s := season_uc_tnTransformInput(in)
211 |
212 | return v.parseFallback(in, s)
213 | }
214 |
--------------------------------------------------------------------------------
/internal/test/season_uc_tt_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v4.0.7
3 |
4 | package test
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "slices"
10 | "strconv"
11 | "strings"
12 | )
13 |
14 | // AllSeason_Uc_Tts lists all 4 values in order.
15 | var AllSeason_Uc_Tts = []Season_Uc_Tt{
16 | Spring_Uc_Tt, Summer_Uc_Tt, Autumn_Uc_Tt, Winter_Uc_Tt,
17 | }
18 |
19 | const (
20 | season_uc_ttEnumStrings = "SPRINGSUMMERAUTUMNWINTER"
21 | season_uc_ttTextStrings = "SprgSumrAutmWint"
22 | )
23 |
24 | var (
25 | season_uc_ttEnumIndex = [...]uint16{0, 6, 12, 18, 24}
26 | season_uc_ttTextIndex = [...]uint16{0, 4, 8, 12, 16}
27 | )
28 |
29 | // String returns the literal string representation of a Season_Uc_Tt, which is
30 | // the same as the const identifier but without prefix or suffix.
31 | func (v Season_Uc_Tt) String() string {
32 | o := v.Ordinal()
33 | return v.toString(o, season_uc_ttEnumStrings, season_uc_ttEnumIndex[:])
34 | }
35 |
36 | // Ordinal returns the ordinal number of a Season_Uc_Tt. This is an integer counting
37 | // from zero. It is *not* the same as the const number assigned to the value.
38 | func (v Season_Uc_Tt) Ordinal() int {
39 | switch v {
40 | case Spring_Uc_Tt:
41 | return 0
42 | case Summer_Uc_Tt:
43 | return 1
44 | case Autumn_Uc_Tt:
45 | return 2
46 | case Winter_Uc_Tt:
47 | return 3
48 | }
49 | return -1
50 | }
51 |
52 | func (v Season_Uc_Tt) toString(o int, concats string, indexes []uint16) string {
53 | if o < 0 || o >= len(AllSeason_Uc_Tts) {
54 | return fmt.Sprintf("Season_Uc_Tt(%d)", v)
55 | }
56 | return concats[indexes[o]:indexes[o+1]]
57 | }
58 |
59 | // IsValid determines whether a Season_Uc_Tt is one of the defined constants.
60 | func (v Season_Uc_Tt) IsValid() bool {
61 | return v.Ordinal() >= 0
62 | }
63 |
64 | // Int returns the int value, which is not necessarily the same as the ordinal.
65 | // This facilitates polymorphism (see enum.IntEnum).
66 | func (v Season_Uc_Tt) Int() int {
67 | return int(v)
68 | }
69 |
70 | var invalidSeason_Uc_TtValue = func() Season_Uc_Tt {
71 | var v Season_Uc_Tt
72 | for {
73 | if !slices.Contains(AllSeason_Uc_Tts, v) {
74 | return v
75 | }
76 | v++
77 | } // AllSeason_Uc_Tts is a finite set so loop will terminate eventually
78 | }()
79 |
80 | // Season_Uc_TtOf returns a Season_Uc_Tt based on an ordinal number. This is the inverse of Ordinal.
81 | // If the ordinal is out of range, an invalid Season_Uc_Tt is returned.
82 | func Season_Uc_TtOf(v int) Season_Uc_Tt {
83 | if 0 <= v && v < len(AllSeason_Uc_Tts) {
84 | return AllSeason_Uc_Tts[v]
85 | }
86 | return invalidSeason_Uc_TtValue
87 | }
88 |
89 | // Parse parses a string to find the corresponding Season_Uc_Tt, accepting one of the string values or
90 | // a number. It is used by AsSeason_Uc_Tt.
91 | //
92 | // Usage Example
93 | //
94 | // v := new(Season_Uc_Tt)
95 | // err := v.Parse(s)
96 | // ... etc
97 | func (v *Season_Uc_Tt) Parse(in string) error {
98 | if v.parseNumber(in) {
99 | return nil
100 | }
101 |
102 | s := season_uc_ttTransformInput(in)
103 |
104 | return v.parseFallback(in, s)
105 | }
106 |
107 | // parseNumber attempts to convert a decimal value.
108 | // Only numbers that correspond to the enumeration are valid.
109 | func (v *Season_Uc_Tt) parseNumber(s string) (ok bool) {
110 | num, err := strconv.ParseInt(s, 10, 64)
111 | if err == nil {
112 | *v = Season_Uc_Tt(num)
113 | return v.IsValid()
114 | }
115 | return false
116 | }
117 |
118 | func (v *Season_Uc_Tt) parseFallback(in, s string) error {
119 | if v.parseString(s, season_uc_ttEnumStrings, season_uc_ttEnumIndex[:]) {
120 | return nil
121 | }
122 |
123 | return errors.New(in + ": unrecognised season_uc_tt")
124 | }
125 |
126 | func (v *Season_Uc_Tt) parseString(s string, concats string, indexes []uint16) (ok bool) {
127 | var i0 uint16 = 0
128 |
129 | for j := 1; j < len(indexes); j++ {
130 | i1 := indexes[j]
131 | p := concats[i0:i1]
132 | if s == p {
133 | *v = AllSeason_Uc_Tts[j-1]
134 | return true
135 | }
136 | i0 = i1
137 | }
138 | return false
139 | }
140 |
141 | // season_uc_ttTransformInput may alter input strings before they are parsed.
142 | // This function is pluggable and is initialised using command-line flags
143 | // -ic -lc -uc -unsnake.
144 | var season_uc_ttTransformInput = func(in string) string {
145 | return strings.ToUpper(in)
146 | }
147 |
148 | // AsSeason_Uc_Tt parses a string to find the corresponding Season_Uc_Tt, accepting either one of the string values or
149 | // a number. It wraps Parse.
150 | func AsSeason_Uc_Tt(s string) (Season_Uc_Tt, error) {
151 | var v = new(Season_Uc_Tt)
152 | err := v.Parse(s)
153 | return *v, err
154 | }
155 |
156 | // MustParseSeason_Uc_Tt is similar to AsSeason_Uc_Tt except that it panics on error.
157 | func MustParseSeason_Uc_Tt(s string) Season_Uc_Tt {
158 | v, err := AsSeason_Uc_Tt(s)
159 | if err != nil {
160 | panic(err)
161 | }
162 | return v
163 | }
164 |
165 | // MarshalText converts values to bytes suitable for transmission via XML, JSON etc.
166 | func (v Season_Uc_Tt) MarshalText() ([]byte, error) {
167 | s, err := v.marshalText()
168 | return []byte(s), err
169 | }
170 |
171 | // Text returns the representation used for transmission via XML, JSON etc.
172 | func (v Season_Uc_Tt) Text() string {
173 | s, _ := v.marshalText()
174 | return s
175 | }
176 |
177 | // marshalText converts values to bytes suitable for transmission via XML, JSON etc.
178 | // The representation is chosen according to 'text' struct tags.
179 | func (v Season_Uc_Tt) marshalText() (string, error) {
180 | o := v.Ordinal()
181 | if o < 0 {
182 | return v.marshalNumberStringOrError()
183 | }
184 |
185 | return v.toString(o, season_uc_ttTextStrings, season_uc_ttTextIndex[:]), nil
186 | }
187 |
188 | func (v Season_Uc_Tt) marshalNumberStringOrError() (string, error) {
189 | bs, err := v.marshalNumberOrError()
190 | return string(bs), err
191 | }
192 |
193 | func (v Season_Uc_Tt) marshalNumberOrError() ([]byte, error) {
194 | // disallow lenient marshaling
195 | return nil, v.invalidError()
196 | }
197 |
198 | func (v Season_Uc_Tt) invalidError() error {
199 | return fmt.Errorf("%d is not a valid season_uc_tt", v)
200 | }
201 |
202 | // UnmarshalText converts transmitted values to ordinary values.
203 | func (v *Season_Uc_Tt) UnmarshalText(bs []byte) error {
204 | return v.unmarshalText(string(bs))
205 | }
206 |
207 | func (v *Season_Uc_Tt) unmarshalText(in string) error {
208 | if v.parseNumber(in) {
209 | return nil
210 | }
211 |
212 | s := season_uc_ttTransformInput(in)
213 |
214 | if v.parseString(s, season_uc_ttTextStrings, season_uc_ttTextIndex[:]) {
215 | return nil
216 | }
217 |
218 | return v.parseFallback(in, s)
219 | }
220 |
--------------------------------------------------------------------------------
/internal/test/simple/season_json.go:
--------------------------------------------------------------------------------
1 | package simple
2 |
3 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Ji -suffix _Nc_Ji -s -marshaljson identifier
4 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Jn -suffix _Nc_Jn -s -marshaljson number
5 | //go:generate enumeration -v -f -i season_json.go -type Season_Nc_Js -suffix _Nc_Js -s
6 |
7 | type (
8 | Season_Nc_Ji uint
9 | Season_Nc_Jn uint
10 | Season_Nc_Js uint
11 | )
12 |
13 | const (
14 | Spring_Nc_Ji, Summer_Nc_Ji, Autumn_Nc_Ji, Winter_Nc_Ji Season_Nc_Ji = 1, 2, 3, 4
15 | )
16 |
17 | const (
18 | Spring_Nc_Jn, Summer_Nc_Jn, Autumn_Nc_Jn, Winter_Nc_Jn Season_Nc_Jn = 1, 2, 3, 4
19 | )
20 |
21 | const (
22 | _ Season_Nc_Js = iota
23 | Spring_Nc_Js // json:"Sprg"
24 | Summer_Nc_Js // json:"Sumr"
25 | Autumn_Nc_Js // json:"Autm"
26 | Winter_Nc_Js // json:"Wint"
27 | )
28 |
29 | //=================================================================================================
30 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Ji -suffix _Uc_Ji -uc -s -marshaljson identifier
31 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Jn -suffix _Uc_Jn -uc -s -marshaljson number
32 | //go:generate enumeration -v -f -i season_json.go -type Season_Uc_Js -suffix _Uc_Js -uc -s
33 |
34 | type (
35 | Season_Uc_Ji uint
36 | Season_Uc_Jn uint
37 | Season_Uc_Js uint
38 | )
39 |
40 | const (
41 | Spring_Uc_Ji, Summer_Uc_Ji, Autumn_Uc_Ji, Winter_Uc_Ji Season_Uc_Ji = 1, 2, 3, 4
42 | )
43 |
44 | const (
45 | _ Season_Uc_Jn = iota
46 | Spring_Uc_Jn
47 | Summer_Uc_Jn
48 | Autumn_Uc_Jn // 3
49 | Winter_Uc_Jn
50 | )
51 |
52 | const (
53 | _ Season_Uc_Js = iota
54 | Spring_Uc_Js // json:"Sprg"
55 | Summer_Uc_Js // json:"Sumr"
56 | Autumn_Uc_Js // json:"Autm"
57 | Winter_Uc_Js // json:"Wint"
58 | )
59 |
--------------------------------------------------------------------------------
/internal/test/simple/season_sql.go:
--------------------------------------------------------------------------------
1 | package simple
2 |
3 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Si -suffix _Nc_Si -s -store identifier
4 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Sn -suffix _Nc_Sn -s -store number
5 | //go:generate enumeration -v -f -i season_sql.go -type Season_Nc_Ss -suffix _Nc_Ss -s
6 |
7 | type (
8 | Season_Nc_Si uint
9 | Season_Nc_Sn uint
10 | Season_Nc_Ss uint
11 | )
12 |
13 | const (
14 | Spring_Nc_Si, Summer_Nc_Si, Autumn_Nc_Si, Winter_Nc_Si Season_Nc_Si = 1, 2, 3, 4
15 | )
16 |
17 | const (
18 | Spring_Nc_Sn, Summer_Nc_Sn, Autumn_Nc_Sn, Winter_Nc_Sn Season_Nc_Sn = 1, 2, 3, 4
19 | )
20 |
21 | const (
22 | _ Season_Nc_Ss = iota
23 | Spring_Nc_Ss // sql:"Sprg"
24 | Summer_Nc_Ss // sql:"Sumr"
25 | Autumn_Nc_Ss // sql:"Autm"
26 | Winter_Nc_Ss // sql:"Wint"
27 | )
28 |
29 | //=================================================================================================
30 | //go:generate enumeration -v -f -i season_sql.go -type Season_Uc_Si -suffix _Uc_Si -uc -s -store identifier
31 | //go:generate enumeration -v -f -i season_sql.go -type Season_Uc_Sn -suffix _Uc_Sn -uc -s -store number
32 |
33 | type (
34 | Season_Uc_Si uint
35 | Season_Uc_Sn uint
36 | )
37 |
38 | const (
39 | Spring_Uc_Si, Summer_Uc_Si, Autumn_Uc_Si, Winter_Uc_Si Season_Uc_Si = 1, 2, 3, 4
40 | )
41 |
42 | const (
43 | Spring_Uc_Sn, Summer_Uc_Sn, Autumn_Uc_Sn, Winter_Uc_Sn Season_Uc_Sn = 1, 2, 3, 4
44 | )
45 |
--------------------------------------------------------------------------------
/internal/test/simple/season_text.go:
--------------------------------------------------------------------------------
1 | package simple
2 |
3 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Ti -suffix _Nc_Ti -s -marshaltext identifier
4 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Tn -suffix _Nc_Tn -s -marshaltext number
5 | //go:generate enumeration -v -f -i season_text.go -type Season_Nc_Ts -suffix _Nc_Ts -s
6 |
7 | type (
8 | Season_Nc_Ti uint
9 | Season_Nc_Tn uint
10 | Season_Nc_Ts uint
11 | )
12 |
13 | const (
14 | Spring_Nc_Ti, Summer_Nc_Ti, Autumn_Nc_Ti, Winter_Nc_Ti Season_Nc_Ti = 1, 2, 3, 4
15 | )
16 |
17 | const (
18 | Spring_Nc_Tn, Summer_Nc_Tn, Autumn_Nc_Tn, Winter_Nc_Tn Season_Nc_Tn = 1, 2, 3, 4
19 | )
20 |
21 | const (
22 | _ Season_Nc_Ts = iota
23 | Spring_Nc_Tt // text:"Sprg"
24 | Summer_Nc_Tt // text:"Sumr"
25 | Autumn_Nc_Tt // text:"Autm"
26 | Winter_Nc_Tt // text:"Wint"
27 | )
28 |
29 | //=================================================================================================
30 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Ti -suffix _Uc_Ti -uc -s -marshaltext identifier
31 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Tn -suffix _Uc_Tn -uc -s -marshaltext number
32 | //go:generate enumeration -v -f -i season_text.go -type Season_Uc_Ts -suffix _Uc_Ts -uc -s
33 |
34 | type (
35 | Season_Uc_Ti uint
36 | Season_Uc_Tn uint
37 | Season_Uc_Ts uint
38 | )
39 |
40 | const (
41 | Spring_Uc_Ti, Summer_Uc_Ti, Autumn_Uc_Ti, Winter_Uc_Ti Season_Uc_Ti = 1, 2, 3, 4
42 | )
43 |
44 | const (
45 | Spring_Uc_Tn, Summer_Uc_Tn, Autumn_Uc_Tn, Winter_Uc_Tn Season_Uc_Tn = 1, 2, 3, 4
46 | )
47 |
48 | const (
49 | _ Season_Uc_Ts = iota
50 | Spring_Uc_Tt // text:"Sprg"
51 | Summer_Uc_Tt // text:"Sumr"
52 | Autumn_Uc_Tt // text:"Autm"
53 | Winter_Uc_Tt // text:"Wint"
54 | )
55 |
--------------------------------------------------------------------------------
/internal/transform/case.go:
--------------------------------------------------------------------------------
1 | package transform
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | //go:generate enumeration -type Case
9 |
10 | type Case int
11 |
12 | const (
13 | Stet Case = iota
14 | Upper
15 | Lower
16 | )
17 |
18 | func Of(lowercase, uppercase bool) Case {
19 | if lowercase {
20 | return Lower
21 | } else if uppercase {
22 | return Upper
23 | }
24 | return Stet
25 | }
26 |
27 | func (c Case) NoOp() bool {
28 | return c == Stet
29 | }
30 |
31 | func (c Case) Transform(s string) string {
32 | switch c {
33 | case Upper:
34 | return strings.ToUpper(s)
35 | case Lower:
36 | return strings.ToLower(s)
37 | }
38 | return s
39 | }
40 |
41 | func (c Case) Expression(s string) string {
42 | switch c {
43 | case Upper:
44 | return fmt.Sprintf("strings.ToUpper(%s)", s)
45 | case Lower:
46 | return fmt.Sprintf("strings.ToLower(%s)", s)
47 | }
48 | return s
49 | }
50 |
51 | func (c Case) Imports() []string {
52 | switch c {
53 | case Upper, Lower:
54 | return []string{"strings"}
55 | }
56 | return nil
57 | }
58 |
--------------------------------------------------------------------------------
/internal/transform/case_enum.go:
--------------------------------------------------------------------------------
1 | // generated code - do not edit
2 | // github.com/rickb777/enumeration/v4 v3.0.2
3 |
4 | package transform
5 |
6 | import (
7 | "errors"
8 | "fmt"
9 | "strconv"
10 | )
11 |
12 | // AllCases lists all 3 values in order.
13 | var AllCases = []Case{
14 | Stet, Upper, Lower,
15 | }
16 |
17 | const (
18 | caseEnumStrings = "StetUpperLower"
19 | )
20 |
21 | var (
22 | caseEnumIndex = [...]uint16{0, 4, 9, 14}
23 | )
24 |
25 | // String returns the literal string representation of a Case, which is
26 | // the same as the const identifier but without prefix or suffix.
27 | func (v Case) String() string {
28 | o := v.Ordinal()
29 | return v.toString(o, caseEnumStrings, caseEnumIndex[:])
30 | }
31 |
32 | func (v Case) toString(o int, concats string, indexes []uint16) string {
33 | if o < 0 || o >= len(AllCases) {
34 | return fmt.Sprintf("Case(%d)", v)
35 | }
36 | return concats[indexes[o]:indexes[o+1]]
37 | }
38 |
39 | // Ordinal returns the ordinal number of a Case. This is an integer counting
40 | // from zero. It is *not* the same as the const number assigned to the value.
41 | func (v Case) Ordinal() int {
42 | switch v {
43 | case Stet:
44 | return 0
45 | case Upper:
46 | return 1
47 | case Lower:
48 | return 2
49 | }
50 | return -1
51 | }
52 |
53 | // IsValid determines whether a Case is one of the defined constants.
54 | func (v Case) IsValid() bool {
55 | return v.Ordinal() >= 0
56 | }
57 |
58 | // CaseOf returns a Case based on an ordinal number. This is the inverse of Ordinal.
59 | // If the ordinal is out of range, an invalid Case is returned.
60 | func CaseOf(v int) Case {
61 | if 0 <= v && v < len(AllCases) {
62 | return AllCases[v]
63 | }
64 | // an invalid result
65 | return Stet + Upper + Lower + 1
66 | }
67 |
68 | // parseNumber attempts to convert a decimal value.
69 | // Only numbers that correspond to the enumeration are valid.
70 | func (v *Case) parseNumber(s string) (ok bool) {
71 | num, err := strconv.ParseInt(s, 10, 64)
72 | if err == nil {
73 | *v = Case(num)
74 | return v.IsValid()
75 | }
76 | return false
77 | }
78 |
79 | // Parse parses a string to find the corresponding Case, accepting one of the string values or
80 | // a number. The input representation is determined by None. It is used by AsCase.
81 | //
82 | // Usage Example
83 | //
84 | // v := new(Case)
85 | // err := v.Parse(s)
86 | // ... etc
87 | func (v *Case) Parse(in string) error {
88 | if v.parseNumber(in) {
89 | return nil
90 | }
91 |
92 | s := caseTransformInput(in)
93 |
94 | return v.parseFallback(in, s)
95 | }
96 |
97 | func (v *Case) parseFallback(in, s string) error {
98 | if v.parseString(s, caseEnumStrings, caseEnumIndex[:]) {
99 | return nil
100 | }
101 |
102 | return errors.New(in + ": unrecognised case")
103 | }
104 |
105 | // caseTransformInput may alter input strings before they are parsed.
106 | // This function is pluggable and is initialised using command-line flags
107 | // -ic -lc -uc -unsnake.
108 | var caseTransformInput = func(in string) string {
109 | return in
110 | }
111 |
112 | func (v *Case) parseString(s string, concats string, indexes []uint16) (ok bool) {
113 | var i0 uint16 = 0
114 |
115 | for j := 1; j < len(indexes); j++ {
116 | i1 := indexes[j]
117 | p := concats[i0:i1]
118 | if s == p {
119 | *v = AllCases[j-1]
120 | return true
121 | }
122 | i0 = i1
123 | }
124 | return false
125 | }
126 |
127 | // AsCase parses a string to find the corresponding Case, accepting either one of the string values or
128 | // a number. The input representation is determined by caseMarshalTextRep. It wraps Parse.
129 | func AsCase(s string) (Case, error) {
130 | var v = new(Case)
131 | err := v.Parse(s)
132 | return *v, err
133 | }
134 |
135 | // MustParseCase is similar to AsCase except that it panics on error.
136 | func MustParseCase(s string) Case {
137 | v, err := AsCase(s)
138 | if err != nil {
139 | panic(err)
140 | }
141 | return v
142 | }
143 |
--------------------------------------------------------------------------------
/internal/transform/unsnake.go:
--------------------------------------------------------------------------------
1 | package transform
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | type Transform interface {
9 | NoOp() bool
10 | Transform(s string) string
11 | Expression(s string) string
12 | Imports() []string
13 | }
14 |
15 | type Transforms []Transform
16 |
17 | func ListOf(ts ...Transform) (list Transforms) {
18 | for _, t := range ts {
19 | if !t.NoOp() {
20 | list = append(list, t)
21 | }
22 | }
23 | return list
24 | }
25 |
26 | func (ts Transforms) Transform(s string) string {
27 | for _, t := range ts {
28 | s = t.Transform(s)
29 | }
30 | return s
31 | }
32 |
33 | func (ts Transforms) Expression(s string) string {
34 | for _, t := range ts {
35 | s = t.Expression(s)
36 | }
37 | return s
38 | }
39 |
40 | func (ts Transforms) Imports() (list []string) {
41 | for _, t := range ts {
42 | list = append(list, t.Imports()...)
43 | }
44 | return list // may contain duplicates
45 | }
46 |
47 | //-------------------------------------------------------------------------------------------------
48 |
49 | type Unsnake bool
50 |
51 | func (u Unsnake) NoOp() bool {
52 | return !bool(u)
53 | }
54 |
55 | func (u Unsnake) Transform(s string) string {
56 | if u {
57 | return strings.ReplaceAll(s, "_", " ")
58 | }
59 | return s
60 | }
61 |
62 | func (u Unsnake) Expression(s string) string {
63 | if u {
64 | return fmt.Sprintf(`strings.ReplaceAll(%s, "_", " ")`, s)
65 | }
66 | return s
67 | }
68 |
69 | func (u Unsnake) Imports() []string {
70 | if u {
71 | return []string{"strings"}
72 | }
73 | return nil
74 | }
75 |
--------------------------------------------------------------------------------
/internal/util/util.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strings"
7 | )
8 |
9 | var Verbose, Dbg bool
10 | var Stdout = os.Stdout
11 |
12 | func Must(err error, args ...interface{}) {
13 | if err != nil {
14 | a2 := make([]interface{}, 0, len(args)+1)
15 | a2 = append(a2, err.Error())
16 | a2 = append(a2, args...)
17 | Fail(a2...)
18 | }
19 | }
20 |
21 | func Fail(args ...interface{}) {
22 | fmt.Fprint(os.Stderr, "Error: ")
23 | fmt.Fprintln(os.Stderr, args...)
24 | os.Exit(1)
25 | }
26 |
27 | func Info(msg string, args ...interface{}) {
28 | if Verbose {
29 | fmt.Fprintf(Stdout, msg, args...)
30 | }
31 | }
32 |
33 | func Debug(msg string, args ...interface{}) {
34 | if Dbg {
35 | fmt.Fprintf(Stdout, msg, args...)
36 | }
37 | }
38 |
39 | func removeAfterS(s, sep string) string {
40 | p := strings.Index(s, sep)
41 | if p < 0 {
42 | return s
43 | }
44 | return s[:p]
45 | }
46 |
47 | func listIndexOf(words []string, target string) int {
48 | for i, w := range words {
49 | if w == target {
50 | return i
51 | }
52 | }
53 | return -1
54 | }
55 |
--------------------------------------------------------------------------------
/magefiles/build.go:
--------------------------------------------------------------------------------
1 | // See https://magefile.org/
2 |
3 | //go:build mage
4 |
5 | // Build steps for the enumeration tool:
6 | package main
7 |
8 | import (
9 | "fmt"
10 | "github.com/magefile/mage/mg"
11 | "github.com/magefile/mage/sh"
12 | "os"
13 | "path/filepath"
14 | "strings"
15 | "time"
16 | )
17 |
18 | var Default = Build
19 |
20 | func Build() error {
21 | if err := os.MkdirAll("bin", 0777); err != nil {
22 | return err
23 | }
24 |
25 | x := ternary(mg.Verbose(), "-x ", "")
26 |
27 | if err := run(
28 | "go build -o bin/enumeration .",
29 | "go clean -testcache",
30 | "rm -f internal/test/*_enum.go internal/test/simple/*_enum.go",
31 | "go test ./internal/parse",
32 | "go generate "+x+"./internal/test",
33 | "rm -f example/*_enum.go",
34 | "go generate "+x+"./example",
35 | "gofmt -l -w -s .",
36 | ); err != nil {
37 | return err
38 | }
39 |
40 | time.Sleep(250 * time.Millisecond) // wait for the files to be stable
41 |
42 | //--- the following section is used in ./enumeration_test.go ---
43 |
44 | if err := os.MkdirAll("temp/example", 0777); err != nil {
45 | return err
46 | }
47 |
48 | if err := run(
49 | "cp -r example temp",
50 | "rm -f temp/example/*_*.go",
51 | "go test ./...",
52 | "go vet ./...",
53 | "rm -rf temp/",
54 | ); err != nil {
55 | return err
56 | }
57 |
58 | return nil
59 | }
60 |
61 | func run(cmds ...string) error {
62 | for _, cmd := range cmds {
63 | parts := dropBlanks(strings.Split(cmd, " "))
64 | if len(parts) > 0 {
65 | expanded, err := expandGlob(parts[1:])
66 | if err != nil {
67 | return err
68 | }
69 | fmt.Println(strings.Join(parts, " "))
70 | err = sh.RunWith(env, parts[0], expanded...)
71 | if err != nil {
72 | return err
73 | }
74 | }
75 | }
76 | return nil
77 | }
78 |
79 | func dropBlanks(value []string) []string {
80 | words := make([]string, 0, len(value))
81 | for _, word := range value {
82 | word = strings.TrimSpace(word)
83 | if word != "" {
84 | words = append(words, word)
85 | }
86 | }
87 | return words
88 | }
89 |
90 | func expandGlob(value []string) ([]string, error) {
91 | var files []string
92 | for _, v := range value {
93 | matches, err := filepath.Glob(v)
94 | if err != nil {
95 | return nil, err
96 | }
97 | if len(matches) > 0 {
98 | for _, x := range matches {
99 | files = append(files, x)
100 | }
101 | } else {
102 | files = append(files, v)
103 | }
104 | }
105 | return files, nil
106 | }
107 |
108 | var env = setupPathWithBinDir()
109 |
110 | func setupPathWithBinDir() map[string]string {
111 | dir, _ := os.Getwd()
112 | bindir := filepath.Join(dir, "bin")
113 | path := bindir + ":" + os.Getenv("PATH")
114 | return map[string]string{"PATH": path}
115 | }
116 |
117 | func ternary(pred bool, a, b string) string {
118 | if pred {
119 | return a
120 | }
121 | return b
122 | }
123 |
--------------------------------------------------------------------------------
/version.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // appVersion is updated manually just prior to the next tag to be used.
4 | const appVersion = "v4.0.7"
5 |
--------------------------------------------------------------------------------