Test Comparable interface

This commit is contained in:
世界 2022-07-03 01:10:33 +08:00
parent 51fce3d954
commit d002d5ba3b
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
6 changed files with 78 additions and 16 deletions

View file

@ -6,6 +6,7 @@ import (
"sync"
"time"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/x/list"
)
@ -69,8 +70,7 @@ func New[K comparable, V any](options ...Option[K, V]) *LruCache[K, V] {
func (c *LruCache[K, V]) Load(key K) (V, bool) {
entry := c.get(key)
if entry == nil {
var defaultValue V
return defaultValue, false
return common.DefaultValue[V](), false
}
value := entry.value
@ -154,8 +154,7 @@ create:
func (c *LruCache[K, V]) LoadWithExpire(key K) (V, time.Time, bool) {
entry := c.get(key)
if entry == nil {
var defaultValue V
return defaultValue, time.Time{}, false
return common.DefaultValue[V](), time.Time{}, false
}
return entry.value, time.Unix(entry.expires, 0), true

40
common/comparable.go Normal file
View file

@ -0,0 +1,40 @@
package common
type Comparable[T any] interface {
Equals(other T) bool
}
func Equals[T Comparable[T]](obj T, other T) bool {
var anyObj any = obj
var anyOther any = other
if anyObj == nil && anyOther == nil {
return true
} else if anyObj == nil || anyOther == nil {
return false
}
return obj.Equals(other)
}
func IsEmptyByEquals[T Comparable[T]](obj T) bool {
return obj.Equals(DefaultValue[T]())
}
func ComparablePtrEquals[T comparable](obj *T, other *T) bool {
return *obj == *other
}
func PtrEquals[T Comparable[T]](obj *T, other *T) bool {
return Equals(*obj, *other)
}
func ComparableSliceEquals[T comparable](arr []T, otherArr []T) bool {
return len(arr) == len(otherArr) && AllIndexed(arr, func(index int, it T) bool {
return it == otherArr[index]
})
}
func SliceEquals[T Comparable[T]](arr []T, otherArr []T) bool {
return len(arr) == len(otherArr) && AllIndexed(arr, func(index int, it T) bool {
return Equals(it, otherArr[index])
})
}

View file

@ -16,6 +16,15 @@ func Any[T any](array []T, block func(it T) bool) bool {
return false
}
func AnyIndexed[T any](array []T, block func(index int, it T) bool) bool {
for i, it := range array {
if block(i, it) {
return true
}
}
return false
}
func All[T any](array []T, block func(it T) bool) bool {
for _, it := range array {
if !block(it) {
@ -25,6 +34,15 @@ func All[T any](array []T, block func(it T) bool) bool {
return true
}
func AllIndexed[T any](array []T, block func(index int, it T) bool) bool {
for i, it := range array {
if !block(i, it) {
return false
}
}
return true
}
func Contains[T comparable](arr []T, target T) bool {
for i := range arr {
if target == arr[i] {
@ -66,8 +84,7 @@ func Find[T any](arr []T, block func(it T) bool) T {
return it
}
}
var defaultValue T
return defaultValue
return DefaultValue[T]()
}
//go:norace
@ -164,15 +181,18 @@ func PtrOrNil[T any](ptr *T) any {
func PtrValueOrDefault[T any](ptr *T) T {
if ptr == nil {
var defaultValue T
return defaultValue
return DefaultValue[T]()
}
return *ptr
}
func IsEmpty[T comparable](obj T) bool {
return obj == DefaultValue[T]()
}
func DefaultValue[T any]() T {
var defaultValue T
return obj == defaultValue
return defaultValue
}
func Close(closers ...any) error {

View file

@ -11,6 +11,5 @@ func Cast[T any](obj any) (T, bool) {
if u, ok := obj.(WithUpstream); ok {
return Cast[T](u.Upstream())
}
var defaultValue T
return defaultValue, false
return DefaultValue[T](), false
}

View file

@ -1,13 +1,18 @@
package list
import "github.com/sagernet/sing/common"
func (l List[T]) Size() int {
return l.len
}
func (l List[T]) IsEmpty() bool {
return l.len == 0
}
func (l *List[T]) PopBack() T {
if l.len == 0 {
var defaultValue T
return defaultValue
return common.DefaultValue[T]()
}
entry := l.root.prev
l.remove(entry)
@ -16,8 +21,7 @@ func (l *List[T]) PopBack() T {
func (l *List[T]) PopFront() T {
if l.len == 0 {
var defaultValue T
return defaultValue
return common.DefaultValue[T]()
}
entry := l.root.next
l.remove(entry)

View file

@ -130,7 +130,7 @@ func (l *List[T]) move(e, at *Element[T]) {
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
// The element must not be nil.
func (l *List[T]) Remove(e *Element[T]) any {
func (l *List[T]) Remove(e *Element[T]) T {
if e.list == l {
// if e.list == l, l must have been initialized when e was inserted
// in l or l == nil (e is a zero Element) and l.remove will crash