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) (r string) { r = "/" + path.Join(n...) defer func() { for strings.Contains(r, "//") { r = strings.ReplaceAll(r, "//", "/") } }() 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 } // RotateRight rotates the bits in the byte array to the right by n positions func rotateBitsRight(data []byte, n int) { // Normalize n to avoid unnecessary rotations n = n % (len(data) * 8) if n == 0 { return } // To hold the final rotated result inlen := len(data) for k := 0; k < n/8; k++ { last := data[inlen-1] for i := 0; i < inlen-1; i++ { data[inlen-1-i] = data[inlen-2-i] } data[0] = last } n = n % 8 if n == 0 { return } mask := byte(1<> n) | (carry << (8 - n)) carry = nextcarry } data[0] = (data[0] >> n) | (carry << (8 - n)) } func rotateBitsLeft(data []byte, n int) { // Normalize n to avoid unnecessary rotations n = n % (len(data) * 8) if n == 0 { return } // To hold the final rotated result inlen := len(data) for k := 0; k < n/8; k++ { last := data[0] for i := 0; i < inlen-1; i++ { data[i] = data[i+1] } data[inlen-1] = last } n = n % 8 if n == 0 { return } mask := (byte(1<= 0; i-- { nextcarry := data[i] & mask data[i] = (data[i] << n) | (carry >> (8 - n)) carry = nextcarry } } func RotateBits(data []byte, n int) { if n > 0 { rotateBitsRight(data, n) } else { rotateBitsLeft(data, -n) } }