Skip to content

denizgursoy/genum

Repository files navigation

genum

genum is an experimental go enumeration implementation.

Install

go install github.com/denizgursoy/genum

Write comment to a source file in the format

// Enum: Status
// Field: name -> string
// Field: code -> int
// Field: description -> string
// Value: InProgress -> IN_PROGRESS -> 55 -> Records are being processed
// Value: Pending -> PENDING -> 78 -> Waiting for approval
// Value: Blocked -> BLOCKED -> 99 -> Blocked by external reasons
// Value: Done -> DONE -> 193 -> Completed and tested
// Value: Canceled -> CANCELED -> 45 -> Cancel because of time limitations

Execute genum

genum --source=source.go --destination=statues.go --package=status

Enums with a getter for every field will be created

// Code generated by genum DO NOT EDIT

package status

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
)

// Status type definition
type Status struct {
	_ordinal    int
	_name       string
	name        string
	code        int
	description string
}

// Statuses
var (
	InProgress = Status{
		_ordinal:    0,
		_name:       "InProgress",
		name:        "IN_PROGRESS",
		code:        55,
		description: "Records are being processed",
	}

	Pending = Status{
		_ordinal:    1,
		_name:       "Pending",
		name:        "PENDING",
		code:        78,
		description: "Waiting for approval",
	}

	Blocked = Status{
		_ordinal:    2,
		_name:       "Blocked",
		name:        "BLOCKED",
		code:        99,
		description: "Blocked by external reasons",
	}

	Done = Status{
		_ordinal:    3,
		_name:       "Done",
		name:        "DONE",
		code:        193,
		description: "Completed and tested",
	}

	Canceled = Status{
		_ordinal:    4,
		_name:       "Canceled",
		name:        "CANCELED",
		code:        45,
		description: "Cancel because of time limitations",
	}
)

func (s Status) Name() string {
	return s.name
}

func (s Status) Code() int {
	return s.code
}

func (s Status) Description() string {
	return s.description
}

func (s Status) String() string {
	return s._name
}

func (s Status) IsValid() bool {
	return s != Status{}
}

func (s Status) Value() (driver.Value, error) {
	return s._name, nil
}

func (s *Status) Scan(value any) error {
	if value == nil {
		return nil
	}
	if _name, err := driver.String.ConvertValue(value); err == nil {
		for _, eval := range AllStatuses() {
			if eval._name == _name {
				*s = eval
				return nil
			}
		}
	}

	return errors.New("failed to scan Status")
}

func (s Status) MarshalJSON() ([]byte, error) {
	return json.Marshal(s._name)
}

func (s *Status) UnmarshalJSON(bytes []byte) error {
	_name := ""
	if err := json.Unmarshal(bytes, &_name); err != nil {
		return err
	}
	for _, eval := range AllStatuses() {
		if eval._name == _name {
			*s = eval
			return nil
		}
	}

	return errors.New("status does not exist")
}

func AllStatuses() [5]Status {
	return [5]Status{InProgress, Pending, Blocked, Done, Canceled}
}

Start using generated values

package main

import (
	"fmt"
	"encoding/json"
	
	status "github.com/denizgursoy/genum/status"
)

func main() {
	fmt.Println(status.Blocked == status.Canceled) // false
	fmt.Println(status.Blocked == status.Blocked) // true
	fmt.Println(status.Blocked.IsValid()) // true
	fmt.Println(status.Status{}.IsValid()) // false
	type issue struct {
		Name   string        `json:"name"`
		Status status.Status `json:"status"`
	}
	firstIssue := issue{
		Name:   "My first issue",
		Status: status.InProgress,
	}
	marshalledJson, _ := json.Marshal(firstIssue)
	fmt.Println(string(marshalledJson)) // {"name":"My first issue","status":"InProgress"}

	parsedIssue := issue{}
	json.Unmarshal(marshalledJson, &parsedIssue)
	fmt.Println(parsedIssue) // {My first issue InProgress}

}