{{- define "enum_string"}} const ( {{- $enumName := .enum.Name -}} {{- $enumType := .enum.Type -}} {{- $noComments := .nocomments -}} {{- $vars := dict "lastoffset" "0" -}} {{ range $rIndex, $value := .enum.Values }} {{- if $noComments }}{{else}} {{ if eq $value.Name "_"}}// Skipped value.{{else}}// {{$value.PrefixedName}} is a {{$enumName}} of type {{$value.RawName}}.{{end}}{{end}} {{- if $value.Comment}} // {{$value.Comment}} {{- end}} {{$value.PrefixedName}} {{$enumName}} = "{{$value.ValueStr}}" {{- end}} ) {{if .names -}} var ErrInvalid{{.enum.Name}} = fmt.Errorf("not a valid {{.enum.Name}}, try [%s]", strings.Join(_{{.enum.Name}}Names, ", ")) {{- else -}} var ErrInvalid{{.enum.Name}} = errors.New("not a valid {{.enum.Name}}") {{- end}} {{ if .names }}var _{{.enum.Name}}Names = {{namify .enum}} // {{.enum.Name}}Names returns a list of possible string values of {{.enum.Name}}. func {{.enum.Name}}Names() []string { tmp := make([]string, len(_{{.enum.Name}}Names)) copy(tmp, _{{.enum.Name}}Names) return tmp } {{ end -}} {{ if .values }} // {{.enum.Name}}Values returns a list of the values for {{.enum.Name}} func {{.enum.Name}}Values() []{{.enum.Name}} { return []{{.enum.Name}}{ {{ range $rIndex, $value := .enum.Values }}{{ if ne $value.Name "_"}} {{$value.PrefixedName}},{{ end }} {{- end}} } } {{ end -}} // String implements the Stringer interface. func (x {{.enum.Name}}) String() string { return string(x) } // IsValid provides a quick way to determine if the typed value is // part of the allowed enumerated values func (x {{.enum.Name}}) IsValid() bool { _, err := Parse{{.enum.Name}}(string(x)) return err == nil } var _{{.enum.Name}}Value = {{ unmapify .enum .lowercase }} // Parse{{.enum.Name}} attempts to convert a string to a {{.enum.Name}}. func Parse{{.enum.Name}}(name string) ({{.enum.Name}}, error) { if x, ok := _{{.enum.Name}}Value[name]; ok { return x, nil }{{if .nocase }} // Case insensitive parse, do a separate lookup to prevent unnecessary cost of lowercasing a string if we don't need to. if x, ok := _{{.enum.Name}}Value[strings.ToLower(name)]; ok { return x, nil }{{- end}} return {{.enum.Name}}(""), fmt.Errorf("%s is %w", name, ErrInvalid{{.enum.Name}}) } {{ if .mustparse }} // MustParse{{.enum.Name}} converts a string to a {{.enum.Name}}, and panics if is not valid. func MustParse{{.enum.Name}}(name string) {{.enum.Name}} { val, err := Parse{{.enum.Name}}(name) if err != nil { panic(err) } return val } {{end}} {{ if .ptr }} func (x {{.enum.Name}}) Ptr() *{{.enum.Name}} { return &x } {{end}} {{ if .marshal }} // MarshalText implements the text marshaller method. func (x {{.enum.Name}}) MarshalText() ([]byte, error) { return []byte(string(x)), nil } // UnmarshalText implements the text unmarshaller method. func (x *{{.enum.Name}}) UnmarshalText(text []byte) error { tmp, err := Parse{{.enum.Name}}(string(text)) if err != nil { return err } *x = tmp return nil } {{end}} {{ if .anySQLEnabled }} var err{{.enum.Name}}NilPtr = errors.New("value pointer is nil") // one per type for package clashes {{ end }} {{/* SQL stored as a string value */}} {{ if .sql }} {{ if eq .enum.Type "string" }} // Scan implements the Scanner interface. func (x *{{.enum.Name}}) Scan(value interface{}) (err error) { if value == nil { *x = {{.enum.Name}}("") return } // A wider range of scannable types. // driver.Value values at the top of the list for expediency switch v := value.(type) { case string: *x, err = Parse{{.enum.Name}}(v) case []byte: *x, err = Parse{{.enum.Name}}(string(v)) case {{.enum.Name}}: *x = v case *{{.enum.Name}}: if v == nil{ return err{{.enum.Name}}NilPtr } *x = *v case *string: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = Parse{{.enum.Name}}(*v) default: return errors.New("invalid type for {{.enum.Name}}") } return } // Value implements the driver Valuer interface. func (x {{.enum.Name}}) Value() (driver.Value, error) { return x.String(), nil } {{ else if or .sqlint .sqlnullint }} {{/* SQL stored as an integer value */}} var sqlInt{{.enum.Name}}Map = map[int64]{{.enum.Name}}{ {{ range $rIndex, $value := .enum.Values }}{{ if ne $value.Name "_"}} {{ $value.ValueInt }}: {{ $value.PrefixedName }},{{end}} {{- end}} } var sqlInt{{.enum.Name}}Value = map[{{.enum.Name}}]int64{ {{ range $rIndex, $value := .enum.Values }}{{ if ne $value.Name "_"}} {{ $value.PrefixedName }}: {{ $value.ValueInt }},{{end}} {{- end}} } func lookupSqlInt{{.enum.Name}}(val int64) ({{.enum.Name}}, error){ x, ok := sqlInt{{.enum.Name}}Map[val] if !ok{ return x, fmt.Errorf("%v is not %w", val, ErrInvalid{{.enum.Name}}) } return x, nil } // Scan implements the Scanner interface. func (x *{{.enum.Name}}) Scan(value interface{}) (err error) { if value == nil { *x = {{.enum.Name}}("") return } // A wider range of scannable types. // driver.Value values at the top of the list for expediency switch v := value.(type) { case int64: *x, err = lookupSqlInt{{.enum.Name}}(v) case string: *x, err = Parse{{.enum.Name}}(v) case []byte: if val, verr := strconv.ParseInt(string(v), 10, 64); verr == nil { *x, err = lookupSqlInt{{.enum.Name}}(val) } else { // try parsing the value as a string *x, err = Parse{{.enum.Name}}(string(v)) } case {{.enum.Name}}: *x = v case int: *x, err = lookupSqlInt{{.enum.Name}}(int64(v)) case *{{.enum.Name}}: if v == nil{ return err{{.enum.Name}}NilPtr } *x = *v case uint: *x, err = lookupSqlInt{{.enum.Name}}(int64(v)) case uint64: *x, err = lookupSqlInt{{.enum.Name}}(int64(v)) case *int: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = lookupSqlInt{{.enum.Name}}(int64(*v)) case *int64: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = lookupSqlInt{{.enum.Name}}(int64(*v)) case float64: // json marshals everything as a float64 if it's a number *x, err = lookupSqlInt{{.enum.Name}}(int64(v)) case *float64: // json marshals everything as a float64 if it's a number if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = lookupSqlInt{{.enum.Name}}(int64(*v)) case *uint: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = lookupSqlInt{{.enum.Name}}(int64(*v)) case *uint64: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = lookupSqlInt{{.enum.Name}}(int64(*v)) case *string: if v == nil{ return err{{.enum.Name}}NilPtr } *x, err = Parse{{.enum.Name}}(*v) default: return errors.New("invalid type for {{.enum.Name}}") } return } // Value implements the driver Valuer interface. func (x {{.enum.Name}}) Value() (driver.Value, error) { val, ok := sqlInt{{.enum.Name}}Value[x] if !ok{ return nil, ErrInvalid{{.enum.Name}} } return int64(val), nil } {{end}} {{end}} {{ if .flag }} // Set implements the Golang flag.Value interface func. func (x *{{.enum.Name}}) Set(val string) error { v, err := Parse{{.enum.Name}}(val) *x = v return err } // Get implements the Golang flag.Getter interface func. func (x *{{.enum.Name}}) Get() interface{} { return *x } // Type implements the github.com/spf13/pFlag Value interface. func (x *{{.enum.Name}}) Type() string { return "{{.enum.Name}}" } {{end}} {{ if or .sqlnullint .sqlnullstr }} type Null{{.enum.Name}} struct{ {{.enum.Name}} {{.enum.Name}} Valid bool{{/* Add some info as to whether this value was set during unmarshalling or not */}}{{if .marshal }} Set bool{{ end }} } func NewNull{{.enum.Name}}(val interface{}) (x Null{{.enum.Name}}) { err := x.Scan(val) // yes, we ignore this error, it will just be an invalid value. _ = err // make any errcheck linters happy return } // Scan implements the Scanner interface. func (x *Null{{.enum.Name}}) Scan(value interface{}) (err error) { if value == nil { x.{{.enum.Name}}, x.Valid = {{.enum.Name}}(""), false return } err = x.{{.enum.Name}}.Scan(value) x.Valid = (err == nil) return } {{ if .sqlnullint }} // Value implements the driver Valuer interface. func (x Null{{.enum.Name}}) Value() (driver.Value, error) { if !x.Valid{ return nil, nil } // driver.Value accepts int64 for int values. return string(x.{{.enum.Name}}), nil } {{ else }} // Value implements the driver Valuer interface. func (x Null{{.enum.Name}}) Value() (driver.Value, error) { if !x.Valid{ return nil, nil } return x.{{.enum.Name}}.String(), nil } {{ end }} {{ if .marshal }} // MarshalJSON correctly serializes a Null{{.enum.Name}} to JSON. func (n Null{{.enum.Name}}) MarshalJSON() ([]byte, error) { const nullStr = "null" if n.Valid { return json.Marshal(n.{{.enum.Name}}) } return []byte(nullStr), nil } // UnmarshalJSON correctly deserializes a Null{{.enum.Name}} from JSON. func (n *Null{{.enum.Name}}) UnmarshalJSON(b []byte) error { n.Set = true var x interface{} err := json.Unmarshal(b, &x) if err != nil{ return err } err = n.Scan(x) return err } {{ end }} {{ end }} {{ if and .sqlnullint .sqlnullstr }} type Null{{.enum.Name}}Str struct { Null{{.enum.Name}} } func NewNull{{.enum.Name}}Str(val interface{}) (x Null{{.enum.Name}}Str) { x.Scan(val) // yes, we ignore this error, it will just be an invalid value. return } // Value implements the driver Valuer interface. func (x Null{{.enum.Name}}Str) Value() (driver.Value, error) { if !x.Valid{ return nil, nil } return x.{{.enum.Name}}.String(), nil } {{ if .marshal }} // MarshalJSON correctly serializes a Null{{.enum.Name}} to JSON. func (n Null{{.enum.Name}}Str) MarshalJSON() ([]byte, error) { const nullStr = "null" if n.Valid { return json.Marshal(n.{{.enum.Name}}) } return []byte(nullStr), nil } // UnmarshalJSON correctly deserializes a Null{{.enum.Name}} from JSON. func (n *Null{{.enum.Name}}Str) UnmarshalJSON(b []byte) error { n.Set = true var x interface{} err := json.Unmarshal(b, &x) if err != nil{ return err } err = n.Scan(x) return err } {{ end }} {{ end }} {{end}}