Initial QSfera import
This commit is contained in:
+32
@@ -0,0 +1,32 @@
|
||||
load("@rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "pool",
|
||||
srcs = [
|
||||
"big_int.go",
|
||||
"byte_slice.go",
|
||||
"bytes_buffer.go",
|
||||
"error_slice.go",
|
||||
"key_to_error_map.go",
|
||||
"pool.go",
|
||||
],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/pool",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":pool",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "pool_test",
|
||||
srcs = [
|
||||
"byte_slice_test.go",
|
||||
],
|
||||
deps = [
|
||||
":pool",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
import "math/big"
|
||||
|
||||
var bigIntPool = New[*big.Int](allocBigInt, freeBigInt)
|
||||
|
||||
func allocBigInt() *big.Int {
|
||||
return &big.Int{}
|
||||
}
|
||||
|
||||
func freeBigInt(b *big.Int) *big.Int {
|
||||
b.SetInt64(0) // Reset the value to zero
|
||||
return b
|
||||
}
|
||||
|
||||
// BigInt returns a pool of *big.Int instances.
|
||||
func BigInt() *Pool[*big.Int] {
|
||||
return bigIntPool
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
var byteSlicePool = SlicePool[byte]{
|
||||
pool: New[[]byte](allocByteSlice, freeByteSlice),
|
||||
}
|
||||
|
||||
func allocByteSlice() []byte {
|
||||
return make([]byte, 0, 64) // Default capacity of 64 bytes
|
||||
}
|
||||
|
||||
func freeByteSlice(b []byte) []byte {
|
||||
clear(b)
|
||||
b = b[:0] // Reset the slice to zero length
|
||||
return b
|
||||
}
|
||||
|
||||
func ByteSlice() SlicePool[byte] {
|
||||
return byteSlicePool
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package pool
|
||||
|
||||
import "bytes"
|
||||
|
||||
var bytesBufferPool = New[*bytes.Buffer](allocBytesBuffer, freeBytesBuffer)
|
||||
|
||||
func allocBytesBuffer() *bytes.Buffer {
|
||||
return &bytes.Buffer{}
|
||||
}
|
||||
|
||||
func freeBytesBuffer(b *bytes.Buffer) *bytes.Buffer {
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
func BytesBuffer() *Pool[*bytes.Buffer] {
|
||||
return bytesBufferPool
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package pool
|
||||
|
||||
var errorSlicePool = New[[]error](allocErrorSlice, freeErrorSlice)
|
||||
|
||||
func allocErrorSlice() []error {
|
||||
return make([]error, 0, 1)
|
||||
}
|
||||
|
||||
func freeErrorSlice(s []error) []error {
|
||||
// Reset the slice to its zero value
|
||||
return s[:0]
|
||||
}
|
||||
|
||||
func ErrorSlice() *Pool[[]error] {
|
||||
return errorSlicePool
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
var keyToErrorMapPool = New[map[string]error](allocKeyToErrorMap, freeKeyToErrorMap)
|
||||
|
||||
func allocKeyToErrorMap() map[string]error {
|
||||
return make(map[string]error)
|
||||
}
|
||||
|
||||
func freeKeyToErrorMap(m map[string]error) map[string]error {
|
||||
for k := range m {
|
||||
delete(m, k) // Clear the map
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// KeyToErrorMap returns a pool of map[string]error instances.
|
||||
func KeyToErrorMap() *Pool[map[string]error] {
|
||||
return keyToErrorMapPool
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package pool
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Pool[T any] struct {
|
||||
pool sync.Pool
|
||||
destructor func(T) T
|
||||
}
|
||||
|
||||
// New creates a new Pool instance for the type T.
|
||||
// The allocator function is used to create new instances of T when the pool is empty.
|
||||
// The destructor function is used to clean up instances of T before they are returned to the pool.
|
||||
// The destructor should reset the state of T to a clean state, so it can be reused, and
|
||||
// return the modified instance of T. This is required for cases when you reset operations
|
||||
// can modify the underlying data structure, such as slices or maps.
|
||||
func New[T any](allocator func() T, destructor func(T) T) *Pool[T] {
|
||||
return &Pool[T]{
|
||||
pool: sync.Pool{
|
||||
New: func() any {
|
||||
return allocator()
|
||||
},
|
||||
},
|
||||
destructor: destructor,
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves an item of type T from the pool.
|
||||
func (p *Pool[T]) Get() T {
|
||||
//nolint:forcetypeassert
|
||||
return p.pool.Get().(T)
|
||||
}
|
||||
|
||||
// Put returns an item of type T to the pool.
|
||||
// The item is first processed by the destructor function to ensure it is in a clean state.
|
||||
func (p *Pool[T]) Put(item T) {
|
||||
p.pool.Put(p.destructor(item))
|
||||
}
|
||||
|
||||
// SlicePool is a specialized pool for slices of type T. It is identical to Pool[T] but
|
||||
// provides additional functionality to get slices with a specific capacity.
|
||||
type SlicePool[T any] struct {
|
||||
pool *Pool[[]T]
|
||||
}
|
||||
|
||||
func NewSlicePool[T any](allocator func() []T, destructor func([]T) []T) SlicePool[T] {
|
||||
return SlicePool[T]{
|
||||
pool: New(allocator, destructor),
|
||||
}
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) Get() []T {
|
||||
return p.pool.Get()
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) GetCapacity(capacity int) []T {
|
||||
if capacity <= 0 {
|
||||
return p.Get()
|
||||
}
|
||||
s := p.Get()
|
||||
if cap(s) < capacity {
|
||||
s = make([]T, 0, capacity)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) Put(s []T) {
|
||||
p.pool.Put(s)
|
||||
}
|
||||
Reference in New Issue
Block a user