package bytes
import "sync"
type BytesPool struct {
size uint
pool sync.Pool
}
func NewBytesPool(size uint) *BytesPool {
return &BytesPool{
size: size,
pool: sync.Pool{
New: func() any {
return make([]byte, size)
},
},
}
}
func (p *BytesPool) Get() []byte {
return p.pool.Get().([]byte)
}
func (p *BytesPool) Put(data []byte) {
if uint(len(data)) != p.size {
panic("buf size not match pool size")
}
p.pool.Put(data)
}
package errors
import (
"fmt"
"io"
"runtime"
"github.com/pkg/errors"
)
func Trace(err error) error {
if err == nil {
return nil
}
if HasStack(err) {
return err
}
return WithStack(err)
}
func WithStack(err error) error {
if err == nil {
return nil
}
return &ErrorWithStack{
err,
callers(),
}
}
func HasStack(err error) bool {
_, ok := err.(ErrorStack)
return ok
}
type ErrorStack interface {
StackTrace() errors.StackTrace
}
var _ ErrorStack = (*ErrorWithStack)(nil)
type ErrorWithStack struct {
error
*stack
}
func (w *ErrorWithStack) Cause() error { return w.error }
// Unwrap provides compatibility for Go 1.13 error chains.
func (w *ErrorWithStack) Unwrap() error { return w.error }
func (w *ErrorWithStack) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
w.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
type stack []uintptr
func (s *stack) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case st.Flag('+'):
for _, pc := range *s {
f := errors.Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
}
}
}
}
func (s *stack) StackTrace() errors.StackTrace {
f := make([]errors.Frame, len(*s))
for i := 0; i < len(f); i++ {
f[i] = errors.Frame((*s)[i])
}
return f
}
func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
var st stack = pcs[0:n]
return &st
}
package ratelimit
import (
"sync"
"time"
)
// Limiter is counter to limit data
type Limiter struct {
lock sync.Mutex
size uint64
now uint64
duration time.Duration
last time.Time
}
// NewLimiter returns new limiter
func NewLimiter(size uint64) *Limiter {
return &Limiter{
size: size,
now: 0,
duration: time.Second,
last: time.Now(),
}
}
// NewLimiter returns new limiter
func NewLimiterWithDuration(size uint64, duration time.Duration) *Limiter {
return &Limiter{
size: size,
now: 0,
duration: duration,
last: time.Now(),
}
}
// Wait allow you take data
func (l *Limiter) Wait(size uint64) {
if l.size == 0 {
return
}
var s uint64
s = size
for {
var ok bool
var t time.Duration
ok, s, t = l.Try(s)
if ok {
break
}
time.Sleep(t)
}
}
func (l *Limiter) Try(size uint64) (ok bool, remainingCount uint64, waitTime time.Duration) {
if l.size == 0 {
return true, 0, 0
}
l.lock.Lock()
defer l.lock.Unlock()
now := time.Now()
if now.Sub(l.last) > l.duration {
l.now = 0
l.last = time.Now()
}
reamining := l.size - l.now
if reamining >= size {
l.now += size
return true, 0, 0
}
l.now += reamining
return false, size - reamining, l.duration - now.Sub(l.last)
}
// reset internal for test only
func (l *Limiter) reset() {
l.lock.Lock()
defer l.lock.Unlock()
l.now = 0
}
package ratelimit
import (
"io"
)
type RateLimitReadWriteCloser struct {
limiter *Limiter
underlay io.ReadWriteCloser
}
func NewRateLimitReaderWriterCloser(underlay io.ReadWriteCloser, size uint64) io.ReadWriteCloser {
return &RateLimitReadWriteCloser{
limiter: NewLimiter(size),
underlay: underlay,
}
}
func NewRateLimitReaderWriterCloserShared(underlay io.ReadWriteCloser, l *Limiter) io.ReadWriteCloser {
return &RateLimitReadWriteCloser{
limiter: l,
underlay: underlay,
}
}
func (r *RateLimitReadWriteCloser) Close() error {
return r.underlay.Close()
}
func (r *RateLimitReadWriteCloser) Read(p []byte) (int, error) {
n, err := r.underlay.Read(p)
if err != nil {
return n, err
}
r.limiter.Wait(uint64(n))
return n, nil
}
func (r *RateLimitReadWriteCloser) Write(p []byte) (int, error) {
n, err := r.underlay.Write(p)
if err != nil {
return n, err
}
r.limiter.Wait(uint64(n))
return n, nil
}
package json
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
)
func PettryJSON(input JSON) string {
data, err := json.MarshalIndent(input, "", "\t")
if err != nil {
panic(err)
}
return string(data)
}
func MergeJSON(a, b JSON) JSON {
for k, v := range b {
a[k] = v
}
return a
}
func IntoJSON[T any](input T) (JSON, error) {
var data JSON
b, err := json.Marshal(input)
if err != nil {
return nil, err
}
err = json.Unmarshal(b, &data)
if err != nil {
return nil, err
}
return data, nil
}
// Scan scan value into Jsonb, implements sql.Scanner interface
func (j *JSON) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
str, ok := value.(string)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
}
bytes = []byte(str)
}
result := JSON{}
err := json.Unmarshal(bytes, &result)
*j = JSON(result)
return err
}
// Value return json value, implement driver.Valuer interface
func (j JSON) Value() (driver.Value, error) {
return json.Marshal(j)
}
func (j JSON) GormDataType() string {
return "JSON"
}
package objects
import (
"bytes"
"encoding/gob"
)
func RemarshGob[T any](input any) (*T, error) {
buf := bytes.Buffer{}
out := new(T)
if err := gob.NewEncoder(&buf).Encode(input); err != nil {
return nil, err
}
if err := gob.NewDecoder(&buf).Decode(out); err != nil {
return nil, err
}
return out, nil
}
func MustRemarshGob[T any](input any) *T {
r, err := RemarshGob[T](input)
if err != nil {
return nil
}
return r
}
package objects
import (
"encoding/json"
"errors"
"reflect"
)
func RemarshJSON[T any](input any) (*T, error) {
bytes, err := json.Marshal(input)
if err != nil {
return nil, err
}
r := new(T)
if err = json.Unmarshal(bytes, r); err != nil {
return nil, err
}
return r, nil
}
var ErrTypeError = errors.New("type error")
func RemarshJSONReflect[T any](input any, kind reflect.Type) (*T, error) {
data, err := json.Marshal(input)
if err != nil {
return nil, err
}
if kind.Kind() == reflect.Ptr {
typ := kind.Elem()
dst := reflect.New(typ).Elem()
err := json.Unmarshal(data, dst.Addr().Interface())
if err != nil {
return nil, err
}
res, ok := dst.Addr().Interface().(*T)
if !ok {
return nil, ErrTypeError
}
return res, nil
}
dst := reflect.New(kind).Elem()
err = json.Unmarshal(data, dst.Addr().Interface())
if err != nil {
return nil, err
}
res, ok := dst.Interface().(T)
if !ok {
return nil, ErrTypeError
}
return &res, nil
}
package windows
import (
"unicode/utf16"
"unsafe"
)
func GoWString(s *uint16) string {
if s == nil {
return ""
}
p := (*[1<<30 - 1]uint16)(unsafe.Pointer(s))
sz := 0
for p[sz] != 0 {
sz++
}
return string(utf16.Decode(p[:sz:sz]))
}
//go:build !(windows || darwin)
package sysproxy
import "errors"
type OtherSystemProxy struct{}
var _ SystemProxy = (*OtherSystemProxy)(nil)
func (p *OtherSystemProxy) TurnOff() error {
return errors.New("not implemented")
}
func (p *OtherSystemProxy) TurnOn(addrport string) error {
return errors.New("not implemented")
}
func NewSystemProxy() SystemProxy {
return &OtherSystemProxy{}
}
func (p *OtherSystemProxy) Status() (*SystemProxyStatus, error) {
return nil, errors.New("not implemented")
}
package time
import "time"
func MeasureFuncTime(target func()) time.Duration {
t := time.Now()
target()
return time.Since(t)
}