first commit

This commit is contained in:
2023-06-27 09:48:33 +02:00
commit 8fc0220e51
29 changed files with 1315 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
package generate
import (
"crypto/rand"
"encoding/binary"
mathRand "math/rand"
"strconv"
"strings"
)
// ID generates an ID using crypto-random, falling back to math random when that fails
// to avoid disrupting operation because of a faulty RNG.
func ID(prefix string, length int) string {
var data [32]byte
result := strings.Builder{}
result.Grow(length + 32)
result.WriteString(prefix)
pos := 0
for result.Len() < length {
if pos == 0 {
randRead(data[:])
}
result.WriteString(strconv.FormatUint(binary.BigEndian.Uint64(data[pos:pos+8]), 36))
pos = (pos + 8) % 32
}
return result.String()[:length]
}
func randRead(data []byte) {
n, err := rand.Read(data)
if err != nil {
mathRand.Read(data[n:])
}
}
// InternalErrorID generates a long string
func InternalErrorID() string {
return ID("ISE", 32)
}
// TagID generates a location ID. len=8
func TagID(longName string) string {
return friendlyID('T', longName, 8)
}
// CharacterID generates a character ID. len=8
func CharacterID(longName string) string {
return friendlyID('C', longName, 8)
}
func friendlyID(prefix byte, name string, length int) string {
b := strings.Builder{}
b.Grow(4)
b.WriteByte(prefix)
for _, ch := range strings.ToLower(name) {
if ch >= 'a' && ch <= 'z' {
b.WriteRune(ch)
if b.Len() > 3 {
break
}
}
}
return ID(b.String(), length)
}
// StoryID generates a story ID: len=8
func StoryID() string {
return ID("S", 12)
}
// PostID generates a post ID. len=12
func PostID() string {
return ID("P", 16)
}
// AnnotationID generates an annotation.sql ID. len=12
func AnnotationID() string {
return ID("A", 16)
}
+29
View File
@@ -0,0 +1,29 @@
package genutils
func UpsertIntoArray[T comparable](arr []T, values ...T) []T {
outer:
for _, value := range values {
for _, value2 := range arr {
if value2 == value {
continue outer
}
}
arr = append(arr, value)
}
return arr
}
func RemoveFromArray[T comparable](arr []T, values ...T) []T {
for _, value := range values {
for i, value2 := range arr {
if value2 == value {
arr = append(arr[:i], arr[i+1:]...)
break
}
}
}
return arr
}
+5
View File
@@ -0,0 +1,5 @@
package genutils
func Ptr[T any](t T) *T {
return &t
}
+29
View File
@@ -0,0 +1,29 @@
package genutils
type Set[T comparable] struct {
m map[T]bool
a []T
}
func (set *Set[T]) Add(values ...T) {
if set.m == nil {
set.m = make(map[T]bool, len(values)*4)
}
for _, value := range values {
if set.m[value] {
continue
}
set.m[value] = true
set.a = append(set.a, value)
}
}
func (set *Set[T]) Len() int {
return len(set.a)
}
func (set *Set[T]) Values() []T {
return set.a[:len(set.a):len(set.a)]
}
+13
View File
@@ -0,0 +1,13 @@
package genutils
import "sort"
type Lesser[T any] interface {
Less(T) bool
}
func SortSlice[T Lesser[T]](slice []T) {
sort.Slice(slice, func(i, j int) bool {
return slice[i].Less(slice[j])
})
}
+70
View File
@@ -0,0 +1,70 @@
package genutils
type hasValid interface {
Valid() bool
}
func ApplyUpdate[T any](dst *T, value *T) {
if value != nil {
*dst = *value
}
}
func ApplyUpdateValid[T hasValid](dst *T, value *T) {
if value != nil && (*value).Valid() {
*dst = *value
}
}
func ApplyUpdateNonZero[T comparable](dst *T, value *T) {
var zero T
if value != nil && *value != zero {
*dst = *value
}
}
func ApplyUpdateNilZero[T comparable](dst **T, value *T) {
if value != nil {
var zero T
if *value == zero {
*dst = nil
} else {
valueCopy := *value
*dst = &valueCopy
}
}
}
func ApplyMapUpdate[K comparable, V any](dst *map[K]V, src map[K]*V) {
if *dst == nil {
dst = &map[K]V{}
}
for key, value := range src {
if value != nil {
(*dst)[key] = *value
} else {
delete(*dst, key)
}
}
}
func ApplyUpdateMapNilZero[K comparable, V comparable](dst *map[K]V, src map[K]V) {
var zero V
if *dst == nil {
dst = &map[K]V{}
}
for key, value := range src {
if value != zero {
(*dst)[key] = value
} else {
delete(*dst, key)
}
}
}
func ApplyArrayUpdate[T comparable](arr *[]T, upsert []T, remove []T) {
*arr = make([]T, 0, len(*arr)+len(upsert))
*arr = UpsertIntoArray(*arr, upsert...)
*arr = RemoveFromArray(*arr, remove...)
}