-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ feat: add new sub package byteutil provide some bytes utils
- Loading branch information
Showing
6 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package byteutil | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// Buffer wrap and extends the bytes.Buffer | ||
type Buffer struct { | ||
bytes.Buffer | ||
} | ||
|
||
// NewBuffer instance | ||
func NewBuffer() *Buffer { | ||
return &Buffer{} | ||
} | ||
|
||
// WriteAny type value to buffer | ||
func (b *Buffer) WriteAny(vs ...any) { | ||
for _, v := range vs { | ||
_, _ = b.Buffer.WriteString(fmt.Sprint(v)) | ||
} | ||
} | ||
|
||
// QuietWriteByte to buffer | ||
func (b *Buffer) QuietWriteByte(c byte) { | ||
_ = b.WriteByte(c) | ||
} | ||
|
||
// QuietWritef write message to buffer | ||
func (b *Buffer) QuietWritef(tpl string, vs ...any) { | ||
_, _ = b.WriteString(fmt.Sprintf(tpl, vs...)) | ||
} | ||
|
||
// Writeln write message to buffer with newline | ||
func (b *Buffer) Writeln(ss ...string) { | ||
b.QuietWriteln(ss...) | ||
} | ||
|
||
// QuietWriteln write message to buffer with newline | ||
func (b *Buffer) QuietWriteln(ss ...string) { | ||
_, _ = b.WriteString(strings.Join(ss, "")) | ||
_ = b.WriteByte('\n') | ||
} | ||
|
||
// QuietWriteString to buffer | ||
func (b *Buffer) QuietWriteString(ss ...string) { | ||
_, _ = b.WriteString(strings.Join(ss, "")) | ||
} | ||
|
||
// MustWriteString to buffer | ||
func (b *Buffer) MustWriteString(ss ...string) { | ||
_, err := b.WriteString(strings.Join(ss, "")) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
// ResetAndGet buffer string. | ||
func (b *Buffer) ResetAndGet() string { | ||
s := b.String() | ||
b.Reset() | ||
return s | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package byteutil_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/gookit/goutil/byteutil" | ||
"github.com/gookit/goutil/testutil/assert" | ||
) | ||
|
||
func TestBuffer_WriteAny(t *testing.T) { | ||
buf := byteutil.NewBuffer() | ||
|
||
buf.QuietWritef("ab-%s", "c") | ||
buf.QuietWriteByte('d') | ||
assert.Eq(t, "ab-cd", buf.ResetAndGet()) | ||
|
||
buf.QuietWriteString("ab", "-", "cd") | ||
buf.MustWriteString("-ef") | ||
assert.Eq(t, "ab-cd-ef", buf.ResetAndGet()) | ||
|
||
buf.WriteAny(23, "abc") | ||
assert.Eq(t, "23abc", buf.ResetAndGet()) | ||
|
||
buf.Writeln("abc") | ||
assert.Eq(t, "abc\n", buf.ResetAndGet()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Package byteutil Provide some bytes utils functions or structs | ||
package byteutil | ||
|
||
import ( | ||
"crypto/md5" | ||
"fmt" | ||
) | ||
|
||
// Md5 Generate a 32-bit md5 bytes | ||
func Md5(src any) []byte { | ||
h := md5.New() | ||
|
||
if s, ok := src.(string); ok { | ||
h.Write([]byte(s)) | ||
} else { | ||
h.Write([]byte(fmt.Sprint(src))) | ||
} | ||
return h.Sum(nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package byteutil | ||
|
||
import ( | ||
"encoding/base64" | ||
"encoding/hex" | ||
) | ||
|
||
// BytesEncoder interface | ||
type BytesEncoder interface { | ||
Encode(src []byte) []byte | ||
Decode(src []byte) ([]byte, error) | ||
} | ||
|
||
// StdEncoder implement the BytesEncoder | ||
type StdEncoder struct { | ||
encodeFn func(src []byte) []byte | ||
decodeFn func(src []byte) ([]byte, error) | ||
} | ||
|
||
// NewStdEncoder instance | ||
func NewStdEncoder(encFn func(src []byte) []byte, decFn func(src []byte) ([]byte, error)) *StdEncoder { | ||
return &StdEncoder{ | ||
encodeFn: encFn, | ||
decodeFn: decFn, | ||
} | ||
} | ||
|
||
// Encode input | ||
func (e *StdEncoder) Encode(src []byte) []byte { | ||
return e.encodeFn(src) | ||
} | ||
|
||
// Decode input | ||
func (e *StdEncoder) Decode(src []byte) ([]byte, error) { | ||
return e.decodeFn(src) | ||
} | ||
|
||
var ( | ||
// HexEncoder instance | ||
HexEncoder = NewStdEncoder(func(src []byte) []byte { | ||
dst := make([]byte, hex.EncodedLen(len(src))) | ||
hex.Encode(dst, src) | ||
return dst | ||
}, func(src []byte) ([]byte, error) { | ||
n, err := hex.Decode(src, src) | ||
return src[:n], err | ||
}) | ||
|
||
// B64Encoder instance | ||
B64Encoder = NewStdEncoder(func(src []byte) []byte { | ||
b64Dst := make([]byte, base64.StdEncoding.EncodedLen(len(src))) | ||
base64.StdEncoding.Encode(b64Dst, src) | ||
return b64Dst | ||
}, func(src []byte) ([]byte, error) { | ||
dBuf := make([]byte, base64.StdEncoding.DecodedLen(len(src))) | ||
n, err := base64.StdEncoding.Decode(dBuf, src) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return dBuf[:n], err | ||
}) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package byteutil_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/gookit/goutil/byteutil" | ||
"github.com/gookit/goutil/testutil/assert" | ||
) | ||
|
||
func TestB64Encoder(t *testing.T) { | ||
src := []byte("abc1234566") | ||
dst := byteutil.B64Encoder.Encode(src) | ||
assert.NotEmpty(t, dst) | ||
|
||
decSrc, err := byteutil.B64Encoder.Decode(dst) | ||
assert.NoError(t, err) | ||
assert.Eq(t, src, decSrc) | ||
} | ||
|
||
func TestHexEncoder(t *testing.T) { | ||
src := []byte("abc1234566") | ||
dst := byteutil.HexEncoder.Encode(src) | ||
assert.NotEmpty(t, dst) | ||
|
||
decSrc, err := byteutil.HexEncoder.Decode(dst) | ||
assert.NoError(t, err) | ||
assert.Eq(t, src, decSrc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package byteutil | ||
|
||
// ChanPool struct | ||
// | ||
// Usage: | ||
// | ||
// bp := strutil.NewByteChanPool(500, 1024, 1024) | ||
// buf:=bp.Get() | ||
// defer bp.Put(buf) | ||
// // use buf do something ... | ||
// | ||
// refer https://www.flysnow.org/2020/08/21/golang-chan-byte-pool.html | ||
// from https://github.com/minio/minio/blob/master/internal/bpool/bpool.go | ||
type ChanPool struct { | ||
c chan []byte | ||
w int | ||
wcap int | ||
} | ||
|
||
// NewChanPool instance | ||
func NewChanPool(maxSize int, width int, capWidth int) *ChanPool { | ||
return &ChanPool{ | ||
c: make(chan []byte, maxSize), | ||
w: width, | ||
wcap: capWidth, | ||
} | ||
} | ||
|
||
// Get gets a []byte from the BytePool, or creates a new one if none are | ||
// available in the pool. | ||
func (bp *ChanPool) Get() (b []byte) { | ||
select { | ||
case b = <-bp.c: | ||
// reuse existing buffer | ||
default: | ||
// create new buffer | ||
if bp.wcap > 0 { | ||
b = make([]byte, bp.w, bp.wcap) | ||
} else { | ||
b = make([]byte, bp.w) | ||
} | ||
} | ||
return | ||
} | ||
|
||
// Put returns the given Buffer to the BytePool. | ||
func (bp *ChanPool) Put(b []byte) { | ||
select { | ||
case bp.c <- b: | ||
// buffer went back into pool | ||
default: | ||
// buffer didn't go back into pool, just discard | ||
} | ||
} | ||
|
||
// Width returns the width of the byte arrays in this pool. | ||
func (bp *ChanPool) Width() (n int) { | ||
return bp.w | ||
} | ||
|
||
// WidthCap returns the cap width of the byte arrays in this pool. | ||
func (bp *ChanPool) WidthCap() (n int) { | ||
return bp.wcap | ||
} |