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 }