mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
doc: add docment for enum package
This commit is contained in:
68
enum/enum.go
68
enum/enum.go
@@ -26,6 +26,7 @@ type Item[T comparable] struct {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewItem creates a new enum item.
|
||||||
func NewItem[T comparable](value T, name string) *Item[T] {
|
func NewItem[T comparable](value T, name string) *Item[T] {
|
||||||
return &Item[T]{value: value, name: name}
|
return &Item[T]{value: value, name: name}
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ type Pair[T comparable] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewItemsFromPairs creates enum items from a slice of Pair structs.
|
// NewItemsFromPairs creates enum items from a slice of Pair structs.
|
||||||
func NewItems[T comparable](pairs ...Pair[T]) []*Item[T] {
|
func NewItemsFromPairs[T comparable](pairs ...Pair[T]) []*Item[T] {
|
||||||
if len(pairs) == 0 {
|
if len(pairs) == 0 {
|
||||||
return []*Item[T]{}
|
return []*Item[T]{}
|
||||||
}
|
}
|
||||||
@@ -50,37 +51,40 @@ func NewItems[T comparable](pairs ...Pair[T]) []*Item[T] {
|
|||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Item[T]) Value() T {
|
// Value returns the value of the enum item.
|
||||||
return e.value
|
func (it *Item[T]) Value() T {
|
||||||
|
return it.value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Item[T]) Name() string {
|
// Name returns the name of the enum item.
|
||||||
return e.name
|
func (it *Item[T]) Name() string {
|
||||||
|
return it.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Item[T]) String() string {
|
// String returns the string representation of the enum item.
|
||||||
return e.name
|
func (it *Item[T]) String() string {
|
||||||
|
return it.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid checks if the enum item is valid. If a custom check function is provided, it will be used to validate the value.
|
// Valid checks if the enum item is valid. If a custom check function is provided, it will be used to validate the value.
|
||||||
func (e *Item[T]) Valid(checker ...func(T) bool) bool {
|
func (it *Item[T]) Valid(checker ...func(T) bool) bool {
|
||||||
if len(checker) > 0 {
|
if len(checker) > 0 {
|
||||||
return checker[0](e.value) && e.name != ""
|
return checker[0](it.value) && it.name != ""
|
||||||
}
|
}
|
||||||
var zero T
|
var zero T
|
||||||
return e.value != zero && e.name != ""
|
return it.value != zero && it.name != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaler interface.
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
func (e *Item[T]) MarshalJSON() ([]byte, error) {
|
func (it *Item[T]) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(map[string]any{
|
return json.Marshal(map[string]any{
|
||||||
"value": e.value,
|
"value": it.value,
|
||||||
"name": e.name,
|
"name": it.name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
func (e *Item[T]) UnmarshalJSON(data []byte) error {
|
func (it *Item[T]) UnmarshalJSON(data []byte) error {
|
||||||
type alias struct {
|
type alias struct {
|
||||||
Value any `json:"value"`
|
Value any `json:"value"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -99,48 +103,47 @@ func (e *Item[T]) UnmarshalJSON(data []byte) error {
|
|||||||
return fmt.Errorf("invalid type for value, want int family")
|
return fmt.Errorf("invalid type for value, want int family")
|
||||||
}
|
}
|
||||||
converted := reflect.ValueOf(int64(val)).Convert(rv)
|
converted := reflect.ValueOf(int64(val)).Convert(rv)
|
||||||
e.value = converted.Interface().(T)
|
it.value = converted.Interface().(T)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
val, ok := temp.Value.(float64)
|
val, ok := temp.Value.(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid type for value, want uint family")
|
return fmt.Errorf("invalid type for value, want uint family")
|
||||||
}
|
}
|
||||||
converted := reflect.ValueOf(uint64(val)).Convert(rv)
|
converted := reflect.ValueOf(uint64(val)).Convert(rv)
|
||||||
e.value = converted.Interface().(T)
|
it.value = converted.Interface().(T)
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
val, ok := temp.Value.(float64)
|
val, ok := temp.Value.(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid type for value, want float family")
|
return fmt.Errorf("invalid type for value, want float family")
|
||||||
}
|
}
|
||||||
converted := reflect.ValueOf(val).Convert(rv)
|
converted := reflect.ValueOf(val).Convert(rv)
|
||||||
e.value = converted.Interface().(T)
|
it.value = converted.Interface().(T)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
val, ok := temp.Value.(string)
|
val, ok := temp.Value.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid type for value, want string")
|
return fmt.Errorf("invalid type for value, want string")
|
||||||
}
|
}
|
||||||
e.value = any(val).(T)
|
it.value = any(val).(T)
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
val, ok := temp.Value.(bool)
|
val, ok := temp.Value.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid type for value, want bool")
|
return fmt.Errorf("invalid type for value, want bool")
|
||||||
}
|
}
|
||||||
e.value = any(val).(T)
|
it.value = any(val).(T)
|
||||||
default:
|
default:
|
||||||
// 枚举类型底层通常是 int,可以尝试 float64->int64->底层类型
|
|
||||||
val, ok := temp.Value.(float64)
|
val, ok := temp.Value.(float64)
|
||||||
if ok {
|
if ok {
|
||||||
converted := reflect.ValueOf(int64(val)).Convert(rv)
|
converted := reflect.ValueOf(int64(val)).Convert(rv)
|
||||||
e.value = converted.Interface().(T)
|
it.value = converted.Interface().(T)
|
||||||
} else {
|
} else {
|
||||||
val2, ok2 := temp.Value.(T)
|
val2, ok2 := temp.Value.(T)
|
||||||
if !ok2 {
|
if !ok2 {
|
||||||
return fmt.Errorf("invalid type for value")
|
return fmt.Errorf("invalid type for value")
|
||||||
}
|
}
|
||||||
e.value = val2
|
it.value = val2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.name = temp.Name
|
it.name = temp.Name
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +155,7 @@ type Registry[T comparable] struct {
|
|||||||
items []*Item[T]
|
items []*Item[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRegistry creates a new enum registry.
|
||||||
func NewRegistry[T comparable](items ...*Item[T]) *Registry[T] {
|
func NewRegistry[T comparable](items ...*Item[T]) *Registry[T] {
|
||||||
r := &Registry[T]{
|
r := &Registry[T]{
|
||||||
values: make(map[T]*Item[T]),
|
values: make(map[T]*Item[T]),
|
||||||
@@ -250,24 +254,6 @@ func (r *Registry[T]) Contains(value T) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the given value is a valid enum item in the registry.
|
|
||||||
func (r *Registry[T]) Validate(value T) error {
|
|
||||||
if !r.Contains(value) {
|
|
||||||
return fmt.Errorf("invalid enum value: %v", value)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateAll checks if all given values are valid enum items in the registry.
|
|
||||||
func (r *Registry[T]) ValidateAll(values ...T) error {
|
|
||||||
for _, value := range values {
|
|
||||||
if err := r.Validate(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the number of enum items in the registry.
|
// Size returns the number of enum items in the registry.
|
||||||
func (r *Registry[T]) Size() int {
|
func (r *Registry[T]) Size() int {
|
||||||
r.mu.RLock()
|
r.mu.RLock()
|
||||||
|
|||||||
@@ -3,7 +3,19 @@ package enum
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func ExampleNewItem() {
|
func ExampleNewItem() {
|
||||||
items := NewItems(
|
item1 := NewItem(Active, "Active")
|
||||||
|
item2 := NewItem(Inactive, "Inactive")
|
||||||
|
|
||||||
|
fmt.Println(item1.Name(), item1.Value())
|
||||||
|
fmt.Println(item2.Name(), item2.Value())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Active 1
|
||||||
|
// Inactive 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleNewItemsFromPairs() {
|
||||||
|
items := NewItemsFromPairs(
|
||||||
Pair[Status]{Value: Active, Name: "Active"},
|
Pair[Status]{Value: Active, Name: "Active"},
|
||||||
Pair[Status]{Value: Inactive, Name: "Inactive"},
|
Pair[Status]{Value: Inactive, Name: "Inactive"},
|
||||||
)
|
)
|
||||||
@@ -114,41 +126,15 @@ func ExampleRegistry_Items() {
|
|||||||
|
|
||||||
func ExampleRegistry_Contains() {
|
func ExampleRegistry_Contains() {
|
||||||
registry := NewRegistry[Status]()
|
registry := NewRegistry[Status]()
|
||||||
item1 := NewItem(Active, "Active")
|
item := NewItem(Active, "Active")
|
||||||
registry.Add(item1)
|
registry.Add(item)
|
||||||
|
|
||||||
fmt.Println("Contains Active:", registry.Contains(Active))
|
fmt.Println(registry.Contains(Active))
|
||||||
fmt.Println("Contains Inactive:", registry.Contains(Inactive))
|
fmt.Println(registry.Contains(Inactive))
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRegistry_Validate() {
|
|
||||||
registry := NewRegistry[Status]()
|
|
||||||
item1 := NewItem(Active, "Active")
|
|
||||||
item2 := NewItem(Inactive, "Inactive")
|
|
||||||
registry.Add(item1, item2)
|
|
||||||
|
|
||||||
fmt.Println("Validate Active:", registry.Validate(Active))
|
|
||||||
fmt.Println("Validate Inactive:", registry.Validate(Inactive))
|
|
||||||
fmt.Println("Validate Unknown:", registry.Validate(Unknown))
|
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// Validate Active: <nil>
|
// true
|
||||||
// Validate Inactive: <nil>
|
// false
|
||||||
// Validate Unknown: invalid enum value: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRegistry_ValidateAll() {
|
|
||||||
registry := NewRegistry[Status]()
|
|
||||||
item1 := NewItem(Active, "Active")
|
|
||||||
item2 := NewItem(Inactive, "Inactive")
|
|
||||||
registry.Add(item1, item2)
|
|
||||||
|
|
||||||
fmt.Println("ValidateAll Active, Inactive:", registry.ValidateAll(Active, Inactive))
|
|
||||||
fmt.Println("ValidateAll Active, Unknown:", registry.ValidateAll(Active, Unknown))
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// ValidateAll Active, Inactive: <nil>
|
|
||||||
// ValidateAll Active, Unknown: invalid enum value: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleRegistry_Size() {
|
func ExampleRegistry_Size() {
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ const (
|
|||||||
Inactive
|
Inactive
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewItem(t *testing.T) {
|
func TestNewItemsFromPairs(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestNewItem")
|
assert := internal.NewAssert(t, "TestNewItemsFromPairs")
|
||||||
|
|
||||||
items := NewItems(
|
items := NewItemsFromPairs(
|
||||||
Pair[Status]{Value: Active, Name: "Active"},
|
Pair[Status]{Value: Active, Name: "Active"},
|
||||||
Pair[Status]{Value: Inactive, Name: "Inactive"},
|
Pair[Status]{Value: Inactive, Name: "Inactive"},
|
||||||
)
|
)
|
||||||
@@ -128,40 +128,6 @@ func TestRegistry_Contains(t *testing.T) {
|
|||||||
assert.Equal(false, registry.Contains(Inactive))
|
assert.Equal(false, registry.Contains(Inactive))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegistry_Validate(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
assert := internal.NewAssert(t, "TestRegistry_Validate")
|
|
||||||
|
|
||||||
registry := NewRegistry[Status]()
|
|
||||||
item1 := NewItem(Active, "Active")
|
|
||||||
item2 := NewItem(Inactive, "Inactive")
|
|
||||||
registry.Add(item1, item2)
|
|
||||||
|
|
||||||
err := registry.Validate(Active)
|
|
||||||
assert.IsNil(err)
|
|
||||||
err = registry.Validate(Inactive)
|
|
||||||
assert.IsNil(err)
|
|
||||||
|
|
||||||
err = registry.Validate(Unknown)
|
|
||||||
assert.IsNotNil(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegistry_ValidateAll(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
assert := internal.NewAssert(t, "TestRegistry_ValidateAll")
|
|
||||||
|
|
||||||
registry := NewRegistry[Status]()
|
|
||||||
item1 := NewItem(Active, "Active")
|
|
||||||
item2 := NewItem(Inactive, "Inactive")
|
|
||||||
registry.Add(item1, item2)
|
|
||||||
|
|
||||||
err := registry.ValidateAll(Active, Inactive)
|
|
||||||
assert.IsNil(err)
|
|
||||||
|
|
||||||
err = registry.ValidateAll(Active, Unknown)
|
|
||||||
assert.IsNotNil(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegistry_Range(t *testing.T) {
|
func TestRegistry_Range(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestRegistry_Range")
|
assert := internal.NewAssert(t, "TestRegistry_Range")
|
||||||
|
|||||||
Reference in New Issue
Block a user