1
0
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:
dudaodong
2025-10-31 14:48:22 +08:00
parent cbdc3971dd
commit 62f0a96d91
3 changed files with 49 additions and 111 deletions

View File

@@ -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()

View File

@@ -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() {

View File

@@ -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")