github.com/profzone/eden-framework@v1.0.10/internal/generator/files/enum.go (about)

     1  package files
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/profzone/eden-framework/internal/generator/api"
     7  	"github.com/profzone/eden-framework/internal/generator/importer"
     8  	str "github.com/profzone/eden-framework/pkg/strings"
     9  	"github.com/sirupsen/logrus"
    10  	"io"
    11  	"sort"
    12  	"strconv"
    13  )
    14  
    15  type Enum struct {
    16  	PackagePath string
    17  	PackageName string
    18  	Name        string
    19  	Options     api.Enum
    20  	Importer    *importer.PackageImporter
    21  	HasOffset   bool
    22  }
    23  
    24  func NewEnum(packagePath, packageName, name string, options api.Enum, hasOffset bool) *Enum {
    25  	return &Enum{
    26  		PackagePath: packagePath,
    27  		PackageName: packageName,
    28  		Name:        name,
    29  		Options:     options,
    30  		Importer:    importer.NewPackageImporter(packagePath),
    31  		HasOffset:   hasOffset,
    32  	}
    33  }
    34  
    35  func (e *Enum) ConstPrefix() string {
    36  	return str.ToUpperSnakeCase(e.Name)
    37  }
    38  
    39  func (e *Enum) ConstOffset() string {
    40  	return e.ConstPrefix() + "_OFFSET"
    41  }
    42  
    43  func (e *Enum) ConstUnknown() string {
    44  	return e.ConstPrefix() + "_UNKNOWN"
    45  }
    46  
    47  func (e *Enum) InvalidErrorString() string {
    48  	return fmt.Sprintf("Invalid%s", e.Name)
    49  }
    50  
    51  func (e *Enum) ConstKey(key interface{}) string {
    52  	return fmt.Sprintf("%s__%v", e.ConstPrefix(), key)
    53  }
    54  
    55  func (e *Enum) WritePackage(w io.Writer) (err error) {
    56  	_, err = io.WriteString(w, fmt.Sprintf("package %s\n\n", e.PackageName))
    57  	return
    58  }
    59  
    60  func (e *Enum) WriteImports(w io.Writer) (err error) {
    61  	_, err = io.WriteString(w, e.Importer.String())
    62  	return
    63  }
    64  
    65  func (e *Enum) WriteVars(w io.Writer) (err error) {
    66  	_, err = io.WriteString(w, fmt.Sprintf("var %s = %s(\"invalid %s\")\n\n", e.InvalidErrorString(), e.Importer.Use("errors.New"), e.Name))
    67  	return
    68  }
    69  
    70  func (e *Enum) WriteInitFunc(w io.Writer) (err error) {
    71  	_, err = io.WriteString(w, fmt.Sprintf(`func init() {
    72  	`+e.Importer.Use("github.com/profzone/eden-framework/pkg/enumeration.RegisterEnums")+"(\""+e.Name+"\", map[string]string{\n"))
    73  
    74  	for _, option := range e.Options {
    75  		_, err = io.WriteString(w, strconv.Quote(fmt.Sprintf("%v", option.Value))+":"+strconv.Quote(option.Label)+",\n")
    76  		if err != nil {
    77  			return
    78  		}
    79  	}
    80  
    81  	_, err = io.WriteString(w, "})\n}\n\n")
    82  	return
    83  }
    84  
    85  func (e *Enum) WriteParseFromStringFunc(w io.Writer) (err error) {
    86  	funcStr := fmt.Sprintf(`func Parse%sFromString(s string) (%s, error) {
    87  	switch s {
    88  	case %s:
    89  		return %s, nil
    90  `, e.Name, e.Name, strconv.Quote(""), e.ConstUnknown())
    91  
    92  	for _, option := range e.Options {
    93  		funcStr += fmt.Sprintf(`case %s:
    94  		return %s, nil
    95  `, fmt.Sprintf(`"%v"`, option.Value), e.ConstKey(option.Value))
    96  	}
    97  
    98  	funcStr += fmt.Sprintf(`}
    99  	return %s, %s
   100  }
   101  
   102  `, e.ConstUnknown(), e.InvalidErrorString())
   103  	_, err = io.WriteString(w, funcStr)
   104  	return
   105  }
   106  
   107  func (e *Enum) WriteParseFromLabelStringFunc(w io.Writer) (err error) {
   108  	funcStr := fmt.Sprintf(`func Parse%sFromLabelString(s string) (%s, error) {
   109  	switch s {
   110  	case %s:
   111  		return %s, nil
   112  `, e.Name, e.Name, strconv.Quote(""), e.ConstUnknown())
   113  
   114  	for _, option := range e.Options {
   115  		funcStr += fmt.Sprintf(`case %s:
   116  		return %s, nil
   117  `, fmt.Sprintf(`"%v"`, option.Label), e.ConstKey(option.Value))
   118  	}
   119  
   120  	funcStr += fmt.Sprintf(`}
   121  	return %s, %s
   122  }
   123  
   124  `, e.ConstUnknown(), e.InvalidErrorString())
   125  	_, err = io.WriteString(w, funcStr)
   126  	return
   127  }
   128  
   129  func (e *Enum) WriteEnumDescriptor(w io.Writer) (err error) {
   130  	contentStr := fmt.Sprintf(`func (%s) EnumType() string {
   131  	return %s
   132  }
   133  
   134  `, e.Name, strconv.Quote(e.Name))
   135  
   136  	contentStr += fmt.Sprintf(`func (%s) Enums() map[int][]string {
   137  	return map[int][]string{
   138  `, e.Name)
   139  
   140  	for _, option := range e.Options {
   141  		contentStr += fmt.Sprintf("int(%s): {%s, %s},\n", e.ConstKey(option.Value), strconv.Quote(fmt.Sprintf("%s", option.Value)), strconv.Quote(option.Label))
   142  	}
   143  
   144  	contentStr += "}\n}\n\n"
   145  
   146  	_, err = io.WriteString(w, contentStr)
   147  	return
   148  }
   149  
   150  func (e *Enum) WriteStringer(w io.Writer) (err error) {
   151  	contentStr := fmt.Sprintf(`func (v %s) String() string {
   152  	switch v {
   153  	case %s:
   154  		return ""
   155  `, e.Name, e.ConstUnknown())
   156  
   157  	for _, option := range e.Options {
   158  		contentStr += fmt.Sprintf(`case %s:
   159  	return %s
   160  `, e.ConstKey(option.Value), fmt.Sprintf(`"%v"`, option.Value))
   161  	}
   162  
   163  	contentStr += `}
   164  	return "UNKNOWN"
   165  }
   166  
   167  `
   168  
   169  	_, err = io.WriteString(w, contentStr)
   170  	return
   171  }
   172  
   173  func (e *Enum) WriteLabeler(w io.Writer) (err error) {
   174  	contentStr := fmt.Sprintf(`func (v %s) Label() string {
   175  	switch v {
   176  	case %s:
   177  		return ""
   178  `, e.Name, e.ConstUnknown())
   179  
   180  	for _, option := range e.Options {
   181  		contentStr += fmt.Sprintf(`case %s:
   182  	return %s
   183  `, e.ConstKey(option.Value), strconv.Quote(option.Label))
   184  	}
   185  
   186  	contentStr += `}
   187  	return "UNKNOWN"
   188  }
   189  
   190  `
   191  
   192  	_, err = io.WriteString(w, contentStr)
   193  	return
   194  }
   195  
   196  func (e *Enum) WriteTextMarshalerAndUnmarshaler(w io.Writer) (err error) {
   197  	contentStr := fmt.Sprintf(`var _ interface {
   198  	%s
   199  	%s
   200  } = (*%s)(nil)
   201  
   202  func (v %s) MarshalText() ([]byte, error) {
   203  	str := v.String()
   204  	if str == "UNKNOWN" {
   205  		return nil, %s
   206  	}
   207  	return []byte(str), nil
   208  }
   209  
   210  func (v *%s) UnmarshalText(data []byte) (err error) {
   211  	*v, err = Parse%sFromString(string(%s(data)))
   212  	return
   213  }
   214  
   215  `,
   216  		e.Importer.Use("encoding.TextMarshaler"),
   217  		e.Importer.Use("encoding.TextUnmarshaler"),
   218  		e.Name, e.Name, e.InvalidErrorString(), e.Name, e.Name,
   219  		e.Importer.Use("bytes.ToUpper"))
   220  
   221  	_, err = io.WriteString(w, contentStr)
   222  	return
   223  }
   224  
   225  func (e *Enum) WriteScannerAndValuer(w io.Writer) (err error) {
   226  	if !e.HasOffset {
   227  		return
   228  	}
   229  
   230  	contentStr := fmt.Sprintf(`var _ interface {
   231  	%s
   232  	%s
   233  } = (*%s)(nil)
   234  
   235  func (v *%s) Scan(src interface{}) error {
   236  	integer, err := %s(src, %s)
   237  	if err != nil {
   238  		return err
   239  	}
   240  	*v = %s(integer - %s)
   241  	return nil
   242  }
   243  
   244  func (v %s) Value() (%s, error) {
   245  	return int64(v) + %s, nil
   246  }
   247  
   248  `,
   249  		e.Importer.Use("database/sql.Scanner"),
   250  		e.Importer.Use("database/sql/driver.Valuer"),
   251  		e.Name, e.Name,
   252  		e.Importer.Use("github.com/profzone/eden-framework/pkg/enumeration.AsInt64"),
   253  		e.ConstOffset(), e.Name, e.ConstOffset(), e.Name,
   254  		e.Importer.Use("database/sql/driver.Value"),
   255  		e.ConstOffset())
   256  
   257  	_, err = io.WriteString(w, contentStr)
   258  	return
   259  }
   260  
   261  func (e *Enum) WriteAll() string {
   262  	w := bytes.NewBuffer([]byte{})
   263  
   264  	err := e.WriteVars(w)
   265  	if err != nil {
   266  		logrus.Panic(err)
   267  	}
   268  	err = e.WriteInitFunc(w)
   269  	if err != nil {
   270  		logrus.Panic(err)
   271  	}
   272  	err = e.WriteParseFromStringFunc(w)
   273  	if err != nil {
   274  		logrus.Panic(err)
   275  	}
   276  	err = e.WriteParseFromLabelStringFunc(w)
   277  	if err != nil {
   278  		logrus.Panic(err)
   279  	}
   280  	err = e.WriteEnumDescriptor(w)
   281  	if err != nil {
   282  		logrus.Panic(err)
   283  	}
   284  	err = e.WriteStringer(w)
   285  	if err != nil {
   286  		logrus.Panic(err)
   287  	}
   288  	err = e.WriteLabeler(w)
   289  	if err != nil {
   290  		logrus.Panic(err)
   291  	}
   292  	err = e.WriteTextMarshalerAndUnmarshaler(w)
   293  	if err != nil {
   294  		logrus.Panic(err)
   295  	}
   296  	err = e.WriteScannerAndValuer(w)
   297  	if err != nil {
   298  		logrus.Panic(err)
   299  	}
   300  
   301  	return w.String()
   302  }
   303  
   304  func (e *Enum) String() string {
   305  	buf := bytes.NewBuffer([]byte{})
   306  
   307  	content := e.WriteAll()
   308  
   309  	err := e.WritePackage(buf)
   310  	if err != nil {
   311  		logrus.Panic(err)
   312  	}
   313  
   314  	err = e.WriteImports(buf)
   315  	if err != nil {
   316  		logrus.Panic(err)
   317  	}
   318  
   319  	_, err = io.WriteString(buf, content)
   320  	if err != nil {
   321  		logrus.Panic(err)
   322  	}
   323  
   324  	return buf.String()
   325  }
   326  
   327  func (e *Enum) WriteEnumDefinition(w io.Writer) (err error) {
   328  	contentStr := fmt.Sprintf(`// api:enum
   329  type %s uint
   330  
   331  const (
   332  %s
   333  `, e.Name, e.ConstPrefix()+"_UNKNOWN "+e.Name+" = iota")
   334  
   335  	sort.Slice(e.Options, func(i, j int) bool {
   336  		return e.Options[i].Val < e.Options[j].Val
   337  	})
   338  
   339  	var index = 1
   340  	for _, enum := range e.Options {
   341  		val := enum.Val
   342  		if val > index {
   343  			contentStr += `(
   344  
   345  const (
   346  `
   347  			contentStr += fmt.Sprintf("%s__%s %s = iota + %d // %s\n", e.ConstPrefix(), enum.Value.(string), e.Name, val, enum.Label)
   348  			index = val + 1
   349  		} else {
   350  			contentStr += fmt.Sprintf("%s__%s // %s\n", e.ConstPrefix(), enum.Value.(string), enum.Label)
   351  			index++
   352  		}
   353  	}
   354  	contentStr += ")\n\n"
   355  
   356  	_, err = io.WriteString(w, contentStr)
   357  	return
   358  }