Documentation
¶
Index ¶
- func Variant[Interface any, Member any](opts ...Option) any
- type AdjacentlyOptions
- type Declaration
- type Enumeration
- func (b Enumeration[Interface, MatchFn]) IsZero(value Interface) bool
- func (c Enumeration) NoZero() bool
- func (b Enumeration[Interface, MatchFn]) Ordinal(value Interface) int
- func (c Enumeration) Sealed() bool
- func (b Enumeration[Interface, MatchFn]) Switch(value Interface) MatchFn
- func (b Enumeration[Interface, MatchFn]) Types() iter.Seq[reflect.Type]
- type ExternallyOptions
- type InternallyOptions
- type JSON
- type Option
- type UntaggedOptions
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Variant ¶
Variant adds or updates another type variant to an Enum declaration. If no such Enum Declaration exists, a new one is created. Panics, if the Enum is sealed. Also, when adding a new variant, all global settings may be changed. This is intentional, e.g. to introduce future workarounds. Currently, always nil is returned, to allow simple execution at global variable declaration time.
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var _ = enum.Variant[Pet, Dog]()
var _ = enum.Variant[Pet, Cat]()
decl, ok := enum.DeclarationFor[Pet]()
if !ok {
panic("unreachable in this example")
}
for variant := range decl.Variants() {
fmt.Printf("pet type: %s\n", variant.Name())
}
}
Output: pet type: Dog pet type: Cat
Types ¶
type AdjacentlyOptions ¶
type Declaration ¶
type Declaration struct {
// contains filtered or unexported fields
}
func DeclarationFor ¶
func DeclarationFor[Interface any]() (Declaration, bool)
func DeclarationOf ¶
func DeclarationOf(t reflect.Type) (Declaration, bool)
func (Declaration) EnumType ¶
func (d Declaration) EnumType() reflect.Type
func (Declaration) JSON ¶
func (d Declaration) JSON() JSON
func (Declaration) NoZero ¶
func (d Declaration) NoZero() bool
type Enumeration ¶
Enumeration represents a union type declaration and enumerates the declared subtypes for a distinct interface type.
func Declare ¶
func Declare[Interface any, MatchFn any](opts ...Option) Enumeration[Interface, MatchFn]
Declare specifies at runtime a sum type based on a (marker) interface type. The actual members are defined through a (anonymous) function type, whose callbacks parameters define the allowed member types. This declaration must ever occur once per Interface type and as early as possible, thus probably at package level. Afterward, the Enumeration can be used for an exhaustive type switch and the interface type can transparently be used with the included json encoder and decoder package.
MatchFn must look like
func(func(TypA), func(TypB), func(TypC))
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var PetEnum = enum.Declare[Pet, func(func(Dog), func(Cat), func(any))]()
var myPet Pet
myPet = Cat{Name: "Simba"}
PetEnum.Switch(myPet)(
func(dog Dog) {
fmt.Printf("pay tax: %v\n", dog.TaxNumber)
},
func(cat Cat) {
fmt.Printf("clean litterbox: %v\n", cat.Name)
},
func(a any) {
if a != nil {
fmt.Printf("remove vermin: %v\n", a)
}
},
)
}
Output: clean litterbox: Simba
func (Enumeration[Interface, MatchFn]) IsZero ¶
func (b Enumeration[Interface, MatchFn]) IsZero(value Interface) bool
func (Enumeration[Interface, MatchFn]) Ordinal ¶
func (b Enumeration[Interface, MatchFn]) Ordinal(value Interface) int
Ordinal returns either the zero based index of the declared types by MatchFn or -1. If the zero value has not been allowed in the declaration, it panics. If sealed and a non-exact type has been found, it panics and otherwise returns -1.
func (Enumeration[Interface, MatchFn]) Switch ¶
func (b Enumeration[Interface, MatchFn]) Switch(value Interface) MatchFn
type ExternallyOptions ¶
type ExternallyOptions struct {
}
type InternallyOptions ¶
type InternallyOptions struct {
Tag string // name of the tag key in json
}
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
func Adjacently ¶
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
"github.com/worldiety/enum/json"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var _ = enum.Variant[Pet, Dog](
enum.Adjacently("kind", "obj"),
)
var _ = enum.Variant[Pet, Cat]()
var myPet Pet
myPet = Cat{Name: "Simba"}
// Note: to not lose the interface information, you MUST provide the pointer
// to the interface variable, otherwise the type itself is marshalled.
buf, err := json.Marshal(&myPet)
if err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
fmt.Println(string(buf))
var pet2 Pet
if err := json.Unmarshal(buf, &pet2); err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
if pet2 != myPet {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
}
Output: {"kind":"Cat","obj":{"Name":"Simba","Pet":null}}
func Externally ¶
func Externally() Option
Externally is the default
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
"github.com/worldiety/enum/json"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var _ = enum.Variant[Pet, Dog](
// this is the default and can be omitted
enum.Externally(),
)
var _ = enum.Variant[Pet, Cat]()
var myPet Pet
myPet = Cat{Name: "Simba"}
// Note: to not lose the interface information, you MUST provide the pointer
// to the interface variable, otherwise the type itself is marshalled.
buf, err := json.Marshal(&myPet)
if err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
fmt.Println(string(buf))
var pet2 Pet
if err := json.Unmarshal(buf, &pet2); err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
if pet2 != myPet {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
}
Output: {"Cat":{"Name":"Simba","Pet":null}}
func Internally ¶
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
"github.com/worldiety/enum/json"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var _ = enum.Variant[Pet, Dog](
enum.Internally("type"),
)
var _ = enum.Variant[Pet, Cat]()
var myPet Pet
myPet = Cat{Name: "Simba"}
// Note: to not lose the interface information, you MUST provide the pointer
// to the interface variable, otherwise the type itself is marshalled.
buf, err := json.Marshal(&myPet)
if err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
fmt.Println(string(buf))
var pet2 Pet
if err := json.Unmarshal(buf, &pet2); err != nil {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
if pet2 != myPet {
panic(fmt.Errorf("unreachable in this example: %w", err))
}
}
Output: {"Name":"Simba","Pet":null,"type":"Cat"}
func NoZero ¶
func NoZero() Option
Example ¶
package main
import (
"fmt"
"github.com/worldiety/enum"
)
func main() {
type Pet interface {
Eat()
Sleep()
}
type Dog struct {
TaxNumber int
Pet
}
type Cat struct {
Name string
Pet
}
// usually declare it at package level
// it is only for illustration here
var PetEnum = enum.Declare[Pet, func(func(Dog), func(Cat))](
enum.NoZero(),
)
var myPet Pet
myPet = Dog{TaxNumber: 42}
PetEnum.Switch(myPet)(
func(dog Dog) {
fmt.Printf("pay tax: %v\n", dog.TaxNumber)
},
func(cat Cat) {
fmt.Printf("clean litterbox: %v\n", cat.Name)
},
)
}
Output: pay tax: 42
type UntaggedOptions ¶
type UntaggedOptions struct {
}