mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-04 20:37:40 +03:00
Test Comparable interface
This commit is contained in:
parent
51fce3d954
commit
d002d5ba3b
6 changed files with 78 additions and 16 deletions
7
common/cache/lrucache.go
vendored
7
common/cache/lrucache.go
vendored
|
@ -6,6 +6,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/x/list"
|
"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) {
|
func (c *LruCache[K, V]) Load(key K) (V, bool) {
|
||||||
entry := c.get(key)
|
entry := c.get(key)
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
var defaultValue V
|
return common.DefaultValue[V](), false
|
||||||
return defaultValue, false
|
|
||||||
}
|
}
|
||||||
value := entry.value
|
value := entry.value
|
||||||
|
|
||||||
|
@ -154,8 +154,7 @@ create:
|
||||||
func (c *LruCache[K, V]) LoadWithExpire(key K) (V, time.Time, bool) {
|
func (c *LruCache[K, V]) LoadWithExpire(key K) (V, time.Time, bool) {
|
||||||
entry := c.get(key)
|
entry := c.get(key)
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
var defaultValue V
|
return common.DefaultValue[V](), time.Time{}, false
|
||||||
return defaultValue, time.Time{}, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry.value, time.Unix(entry.expires, 0), true
|
return entry.value, time.Unix(entry.expires, 0), true
|
||||||
|
|
40
common/comparable.go
Normal file
40
common/comparable.go
Normal 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])
|
||||||
|
})
|
||||||
|
}
|
|
@ -16,6 +16,15 @@ func Any[T any](array []T, block func(it T) bool) bool {
|
||||||
return false
|
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 {
|
func All[T any](array []T, block func(it T) bool) bool {
|
||||||
for _, it := range array {
|
for _, it := range array {
|
||||||
if !block(it) {
|
if !block(it) {
|
||||||
|
@ -25,6 +34,15 @@ func All[T any](array []T, block func(it T) bool) bool {
|
||||||
return true
|
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 {
|
func Contains[T comparable](arr []T, target T) bool {
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
if target == arr[i] {
|
if target == arr[i] {
|
||||||
|
@ -66,8 +84,7 @@ func Find[T any](arr []T, block func(it T) bool) T {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var defaultValue T
|
return DefaultValue[T]()
|
||||||
return defaultValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:norace
|
//go:norace
|
||||||
|
@ -164,15 +181,18 @@ func PtrOrNil[T any](ptr *T) any {
|
||||||
|
|
||||||
func PtrValueOrDefault[T any](ptr *T) T {
|
func PtrValueOrDefault[T any](ptr *T) T {
|
||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
var defaultValue T
|
return DefaultValue[T]()
|
||||||
return defaultValue
|
|
||||||
}
|
}
|
||||||
return *ptr
|
return *ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmpty[T comparable](obj T) bool {
|
func IsEmpty[T comparable](obj T) bool {
|
||||||
|
return obj == DefaultValue[T]()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultValue[T any]() T {
|
||||||
var defaultValue T
|
var defaultValue T
|
||||||
return obj == defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(closers ...any) error {
|
func Close(closers ...any) error {
|
||||||
|
|
|
@ -11,6 +11,5 @@ func Cast[T any](obj any) (T, bool) {
|
||||||
if u, ok := obj.(WithUpstream); ok {
|
if u, ok := obj.(WithUpstream); ok {
|
||||||
return Cast[T](u.Upstream())
|
return Cast[T](u.Upstream())
|
||||||
}
|
}
|
||||||
var defaultValue T
|
return DefaultValue[T](), false
|
||||||
return defaultValue, false
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
package list
|
package list
|
||||||
|
|
||||||
|
import "github.com/sagernet/sing/common"
|
||||||
|
|
||||||
|
func (l List[T]) Size() int {
|
||||||
|
return l.len
|
||||||
|
}
|
||||||
|
|
||||||
func (l List[T]) IsEmpty() bool {
|
func (l List[T]) IsEmpty() bool {
|
||||||
return l.len == 0
|
return l.len == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List[T]) PopBack() T {
|
func (l *List[T]) PopBack() T {
|
||||||
if l.len == 0 {
|
if l.len == 0 {
|
||||||
var defaultValue T
|
return common.DefaultValue[T]()
|
||||||
return defaultValue
|
|
||||||
}
|
}
|
||||||
entry := l.root.prev
|
entry := l.root.prev
|
||||||
l.remove(entry)
|
l.remove(entry)
|
||||||
|
@ -16,8 +21,7 @@ func (l *List[T]) PopBack() T {
|
||||||
|
|
||||||
func (l *List[T]) PopFront() T {
|
func (l *List[T]) PopFront() T {
|
||||||
if l.len == 0 {
|
if l.len == 0 {
|
||||||
var defaultValue T
|
return common.DefaultValue[T]()
|
||||||
return defaultValue
|
|
||||||
}
|
}
|
||||||
entry := l.root.next
|
entry := l.root.next
|
||||||
l.remove(entry)
|
l.remove(entry)
|
||||||
|
|
|
@ -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.
|
// Remove removes e from l if e is an element of list l.
|
||||||
// It returns the element value e.Value.
|
// It returns the element value e.Value.
|
||||||
// The element must not be nil.
|
// 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 {
|
||||||
// if e.list == l, l must have been initialized when e was inserted
|
// 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
|
// in l or l == nil (e is a zero Element) and l.remove will crash
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue