Files
gocommon/misc.go
2023-12-02 20:30:43 +09:00

144 lines
2.7 KiB
Go

package gocommon
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"math/rand"
"path"
"reflect"
"strconv"
"strings"
"sync/atomic"
"time"
"repositories.action2quare.com/ayo/gocommon/flagx"
)
var devflag = flagx.Bool("dev", false, "")
var sequenceStart = rand.Uint32()
func MakeHttpHandlerPattern(n ...string) string {
r := "/" + path.Join(n...)
if strings.HasSuffix(n[len(n)-1], "/") {
return r + "/"
}
return r
}
func MakeLocalUniqueId() string {
var b [10]byte
now := time.Now()
binary.BigEndian.PutUint32(b[6:10], uint32(now.Unix()))
binary.BigEndian.PutUint32(b[3:7], uint32(now.Nanosecond()))
binary.BigEndian.PutUint32(b[0:4], atomic.AddUint32(&sequenceStart, 1))
u := binary.LittleEndian.Uint64(b[2:])
a := strconv.FormatUint(u, 36)
return a[1:]
}
func SerializeInterface(w io.Writer, val interface{}) (err error) {
if val == nil {
return nil
}
value := reflect.ValueOf(val)
encoder := json.NewEncoder(w)
switch value.Kind() {
case reflect.String:
_, err = w.Write([]byte(value.String()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
_, err = w.Write([]byte(fmt.Sprintf("%d", value.Int())))
case reflect.Float32, reflect.Float64:
_, err = w.Write([]byte(fmt.Sprintf("%f", value.Float())))
case reflect.Bool:
if value.Bool() {
_, err = w.Write([]byte("true"))
} else {
_, err = w.Write([]byte("false"))
}
case reflect.Slice:
switch value.Type().Elem().Kind() {
case reflect.Uint8:
_, err = w.Write(value.Bytes())
default:
var conv []interface{}
for i := 0; i < value.Len(); i++ {
conv = append(conv, value.Index(i).Interface())
}
if len(conv) == 0 {
_, err = w.Write([]byte("[]"))
} else {
err = encoder.Encode(conv)
}
}
case reflect.Interface, reflect.Struct, reflect.Map:
if value.Kind() == reflect.Struct {
err = encoder.Encode(value.Interface())
} else if !value.IsNil() {
err = encoder.Encode(value.Interface())
}
case reflect.Ptr:
if !value.IsNil() {
if wro, ok := value.Interface().(io.WriterTo); ok {
_, err = wro.WriteTo(w)
} else {
err = json.NewEncoder(w).Encode(value.Interface())
}
}
}
return
}
func ShrinkSliceAt[T any](in []T, from int) []T {
if len(in) == 0 {
return in
}
cursor := from
for i := from + 1; i < len(in); i++ {
in[cursor] = in[i]
cursor++
}
return in[:len(in)-1]
}
func ShrinkSlice[T any](in []T, compare func(elem T) bool) []T {
if len(in) == 0 {
return in
}
cursor := 0
for i := 0; i < len(in); i++ {
if compare(in[i]) {
continue
}
in[cursor] = in[i]
cursor++
}
return in[:cursor]
}
func FindOneInSlice[T any](in []T, compare func(elem *T) bool) (int, bool) {
for i, e := range in {
if compare(&e) {
return i, true
}
}
return -1, false
}