feat: docs api design

This commit is contained in:
neo-f
2023-03-22 22:45:17 +08:00
commit 084d0de8bc
52 changed files with 3420 additions and 0 deletions

65
pkg/tools/generics.go Normal file
View File

@@ -0,0 +1,65 @@
package tools
// Map returns a new slice where each element is the result of fn for the corresponding element in the original slice
func Map[T any, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, t := range slice {
result[i] = fn(t)
}
return result
}
// Contains returns true if find appears in slice
func Contains[T comparable](slice []T, find T) bool {
for _, t := range slice {
if t == find {
return true
}
}
return false
}
// IndexOf returns the index of find if it appears in slice. If find is not in slice, -1 will be returned.
func IndexOf[T comparable](slice []T, find T) int {
for i, t := range slice {
if t == find {
return i
}
}
return -1
}
// GroupBy returns a map that is keyed by keySelector and contains a slice of elements returned by valSelector
func GroupBy[T any, K comparable, V any](slice []T, keySelector func(T) K, valSelector func(T) V) map[K][]V {
grouping := make(map[K][]V)
for _, t := range slice {
key := keySelector(t)
grouping[key] = append(grouping[key], valSelector(t))
}
return grouping
}
// ToSet returns a map keyed by keySelector and contains a value of an empty struct
func ToSet[T any, K comparable](slice []T, keySelector func(T) K) *Set[K] {
set := NewSetWithCapacity[K](len(slice))
for _, t := range slice {
set.Add(keySelector(t))
}
return set
}
// ToMap return a map that is keyed keySelector and has the value of valSelector for each element in slice.
// If multiple elements return the same key the element that appears later in slice will be chosen.
func ToMap[T any, K comparable, V any](slice []T, keySelector func(T) K, valSelector func(T) V) map[K]V {
m := make(map[K]V)
for _, t := range slice {
m[keySelector(t)] = valSelector(t)
}
return m
}

101
pkg/tools/set.go Normal file
View File

@@ -0,0 +1,101 @@
package tools
import (
"sync"
)
type Set[T comparable] struct {
mu sync.RWMutex
set map[T]struct{}
}
func NewSetWithCapacity[T comparable](c int) *Set[T] {
set := make(map[T]struct{}, c)
return &Set[T]{set: set}
}
func NewSet[T comparable](elems ...T) *Set[T] {
set := make(map[T]struct{}, len(elems))
for _, elem := range elems {
set[elem] = struct{}{}
}
return &Set[T]{set: set}
}
func (s *Set[T]) Add(ele ...T) *Set[T] {
s.mu.Lock()
defer s.mu.Unlock()
for _, e := range ele {
s.set[e] = struct{}{}
}
return s
}
func (s *Set[T]) Del(ele ...T) *Set[T] {
s.mu.Lock()
defer s.mu.Unlock()
for _, e := range ele {
delete(s.set, e)
}
return s
}
func (s *Set[T]) Has(ele T) bool {
s.mu.RLock()
defer s.mu.RUnlock()
_, exists := s.set[ele]
return exists
}
// 取交集.
func (s *Set[T]) Intersect(other *Set[T]) *Set[T] {
s.mu.RLock()
defer s.mu.RUnlock()
ret := NewSet[T]()
for ele := range s.set {
if other.Has(ele) {
ret.Add(ele)
}
}
return ret
}
func (s *Set[T]) Len() int {
return len(s.set)
}
func (s *Set[T]) Set() map[T]struct{} {
return s.set
}
func (s *Set[T]) Values() []T {
s.mu.RLock()
defer s.mu.RUnlock()
ret := make([]T, 0, len(s.set))
for ele := range s.set {
ret = append(ret, ele)
}
return ret
}
func (s *Set[T]) Compare(other *Set[T]) (less, more *Set[T]) {
less = NewSet[T]()
more = NewSet[T]()
// less: s - other
s.mu.RLock()
other.mu.RLock()
defer s.mu.RUnlock()
defer other.mu.RUnlock()
for ele := range other.set {
if !s.Has(ele) {
less.Add(ele)
}
}
// more: other - s
for ele := range s.set {
if !other.Has(ele) {
more.Add(ele)
}
}
return less, more
}

21
pkg/tools/times.go Normal file
View File

@@ -0,0 +1,21 @@
package tools
import "time"
func FirstDayOfISOWeek(year int, week int, timezone *time.Location) time.Time {
date := time.Date(year, 0, 0, 0, 0, 0, 0, timezone)
isoYear, isoWeek := date.ISOWeek()
for date.Weekday() != time.Monday { // iterate back to Monday
date = date.AddDate(0, 0, -1)
isoYear, isoWeek = date.ISOWeek()
}
for isoYear < year { // iterate forward to the first day of the first week
date = date.AddDate(0, 0, 1)
isoYear, isoWeek = date.ISOWeek()
}
for isoWeek < week { // iterate forward to the first day of the given week
date = date.AddDate(0, 0, 1)
_, isoWeek = date.ISOWeek()
}
return date
}