mirror of
https://github.com/fumiama/orbyte.git
synced 2026-06-10 05:04:14 +08:00
init
This commit is contained in:
12
pbuf/buffer.go
Normal file
12
pbuf/buffer.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package pbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/fumiama/orbyte"
|
||||
)
|
||||
|
||||
// NewBuffer wraps bytes.NewBuffer
|
||||
func (bufferPool BufferPool) NewBuffer(buf []byte) *orbyte.Item[bytes.Buffer] {
|
||||
return bufferPool.p.New(buf)
|
||||
}
|
||||
95
pbuf/bytes.go
Normal file
95
pbuf/bytes.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package pbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/fumiama/orbyte"
|
||||
)
|
||||
|
||||
// Bytes wrap pooled buffer into []byte
|
||||
// while sharing the same pool.
|
||||
type Bytes struct {
|
||||
buf *orbyte.Item[bytes.Buffer]
|
||||
dat []byte
|
||||
}
|
||||
|
||||
// NewBytes alloc sz bytes.
|
||||
func (bufferPool BufferPool) NewBytes(sz int) Bytes {
|
||||
buf := bufferPool.p.New(sz)
|
||||
x := buf.Unwrap()
|
||||
return Bytes{buf: buf, dat: x.Bytes()}
|
||||
}
|
||||
|
||||
// InvolveBytes involve outside buf into pool.
|
||||
func (bufferPool BufferPool) InvolveBytes(b ...byte) Bytes {
|
||||
buf := bufferPool.p.Involve(len(b), bytes.NewBuffer(b))
|
||||
x := buf.Unwrap()
|
||||
return Bytes{buf: buf, dat: x.Bytes()}
|
||||
}
|
||||
|
||||
// ParseBytes convert outside bytes to Bytes safely
|
||||
// without adding it into pool.
|
||||
func (bufferPool BufferPool) ParseBytes(b ...byte) Bytes {
|
||||
buf := bufferPool.p.Parse(len(b), bytes.NewBuffer(b))
|
||||
x := buf.Unwrap()
|
||||
return Bytes{buf: buf, dat: x.Bytes()}
|
||||
}
|
||||
|
||||
// Trans please refer to Item.Trans().
|
||||
func (b Bytes) Trans() (tb Bytes) {
|
||||
tb.buf = b.buf.Trans()
|
||||
return
|
||||
}
|
||||
|
||||
// Len of slice.
|
||||
func (b Bytes) Len() int {
|
||||
return len(b.dat)
|
||||
}
|
||||
|
||||
// Cap of slice.
|
||||
func (b Bytes) Cap() int {
|
||||
return cap(b.dat)
|
||||
}
|
||||
|
||||
// Bytes is the inner value.
|
||||
func (b Bytes) Bytes() []byte {
|
||||
return b.dat
|
||||
}
|
||||
|
||||
// Ref please refer to Item.Ref().
|
||||
func (b Bytes) Ref() (rb Bytes) {
|
||||
rb.buf = b.buf.Ref()
|
||||
return
|
||||
}
|
||||
|
||||
// Copy please refer to Item.Copy().
|
||||
func (b Bytes) Copy() (cb Bytes) {
|
||||
cb.buf = b.buf.Copy()
|
||||
return
|
||||
}
|
||||
|
||||
// SliceFrom dat[from:] with Ref.
|
||||
func (b Bytes) SliceFrom(from int) Bytes {
|
||||
nb := b.Ref()
|
||||
nb.dat = b.dat[from:]
|
||||
return nb
|
||||
}
|
||||
|
||||
// SliceTo dat[:to] with Ref.
|
||||
func (b Bytes) SliceTo(to int) Bytes {
|
||||
nb := b.Ref()
|
||||
nb.dat = b.dat[:to]
|
||||
return nb
|
||||
}
|
||||
|
||||
// Slice dat[from:to] with Ref.
|
||||
func (b Bytes) Slice(from, to int) Bytes {
|
||||
nb := b.Ref()
|
||||
nb.dat = b.dat[from:to]
|
||||
return nb
|
||||
}
|
||||
|
||||
// Destroy please refer to Item.Destroy().
|
||||
func (b Bytes) Destroy() {
|
||||
b.buf.Destroy()
|
||||
}
|
||||
39
pbuf/pbuf.go
Normal file
39
pbuf/pbuf.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// Package pbuf is a lightweight pooled buffer.
|
||||
package pbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/fumiama/orbyte"
|
||||
)
|
||||
|
||||
var bufferPool = NewBufferPool()
|
||||
|
||||
type BufferPool struct {
|
||||
p *orbyte.Pool[bytes.Buffer]
|
||||
}
|
||||
|
||||
func NewBufferPool() BufferPool {
|
||||
return BufferPool{p: orbyte.NewPool[bytes.Buffer](bufpooler{})}
|
||||
}
|
||||
|
||||
// NewBuffer wraps bytes.NewBuffer
|
||||
func NewBuffer(buf []byte) *orbyte.Item[bytes.Buffer] {
|
||||
return bufferPool.NewBuffer(buf)
|
||||
}
|
||||
|
||||
// NewBytes alloc sz bytes.
|
||||
func NewBytes(sz int) Bytes {
|
||||
return bufferPool.NewBytes(sz)
|
||||
}
|
||||
|
||||
// InvolveBytes involve outside buf into pool.
|
||||
func InvolveBytes(b ...byte) Bytes {
|
||||
return bufferPool.InvolveBytes(b...)
|
||||
}
|
||||
|
||||
// ParseBytes convert outside bytes to Bytes safely
|
||||
// without adding it into pool.
|
||||
func ParseBytes(b ...byte) Bytes {
|
||||
return bufferPool.ParseBytes(b...)
|
||||
}
|
||||
21
pbuf/pbuf_test.go
Normal file
21
pbuf/pbuf_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package pbuf
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBytes(t *testing.T) {
|
||||
for i := 0; i < 4096; i++ {
|
||||
b := NewBytes(i)
|
||||
rand.Read(b.Bytes())
|
||||
b.Destroy()
|
||||
}
|
||||
runtime.GC()
|
||||
out, in := bufferPool.p.CountItems()
|
||||
t.Log(out, in)
|
||||
if out != 0 || in != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
68
pbuf/pooler.go
Normal file
68
pbuf/pooler.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package pbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type bufpooler struct{}
|
||||
|
||||
func (bufpooler) New(config any, pooled bytes.Buffer) bytes.Buffer {
|
||||
switch c := config.(type) {
|
||||
case int:
|
||||
pooled.Grow(c)
|
||||
return pooled
|
||||
case []byte:
|
||||
if len(c) > 0 || pooled.Cap() < cap(c) {
|
||||
return *bytes.NewBuffer(c)
|
||||
}
|
||||
return pooled
|
||||
case string:
|
||||
pooled.Grow(len(c))
|
||||
pooled.WriteString(c)
|
||||
return pooled
|
||||
default:
|
||||
panic("config type " + reflect.ValueOf(config).Type().String() + " isn't supported")
|
||||
}
|
||||
}
|
||||
|
||||
func (bufpooler) Parse(obj any, pooled bytes.Buffer) bytes.Buffer {
|
||||
switch o := obj.(type) {
|
||||
case *bytes.Buffer:
|
||||
return *o
|
||||
case bytes.Buffer:
|
||||
return o
|
||||
case []byte:
|
||||
pooled.Write(o)
|
||||
return pooled
|
||||
case string:
|
||||
pooled.WriteString(o)
|
||||
return pooled
|
||||
case io.Reader:
|
||||
_, err := io.Copy(&pooled, o)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return pooled
|
||||
default:
|
||||
panic("object type " + reflect.ValueOf(obj).Type().String() + " isn't supported")
|
||||
}
|
||||
}
|
||||
|
||||
func (bufpooler) Reset(item *bytes.Buffer) {
|
||||
// See https://golang.org/issue/23199
|
||||
const maxSize = 1 << 16
|
||||
if item.Cap() > maxSize { // drop large buffer
|
||||
*item = bytes.Buffer{}
|
||||
return
|
||||
}
|
||||
item.Reset()
|
||||
}
|
||||
|
||||
func (bufpooler) Copy(dst, src *bytes.Buffer) {
|
||||
_, err := io.Copy(dst, src)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user