create project
This commit is contained in:
commit
e9bcb96f3b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea
|
15
go.mod
Normal file
15
go.mod
Normal file
@ -0,0 +1,15 @@
|
||||
module kvs
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/tursom/GoCollections v0.2.7
|
||||
google.golang.org/protobuf v1.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
||||
github.com/timandy/routine v1.1.1 // indirect
|
||||
)
|
45
go.sum
Normal file
45
go.sum
Normal file
@ -0,0 +1,45 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/timandy/routine v1.1.1 h1:6/Z7qLFZj3GrzuRksBFzIG8YGUh8CLhjnnMePBQTrEI=
|
||||
github.com/timandy/routine v1.1.1/go.mod h1:OZHPOKSvqL/ZvqXFkNZyit0xIVelERptYXdAHH00adQ=
|
||||
github.com/tursom/GoCollections v0.2.7 h1:WKbtQt1wuBoYhTXLCahr+BiFPJI8pUEQtsFuKk+V2Cc=
|
||||
github.com/tursom/GoCollections v0.2.7/go.mod h1:uGlIIUhnuK01+AlzYtS/P+ZfqA2Q6MEulrPChiwf3KI=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
59
kv/ArrayCodec.go
Normal file
59
kv/ArrayCodec.go
Normal file
@ -0,0 +1,59 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
// 不推荐使用
|
||||
|
||||
type (
|
||||
arrayCodec[V any] struct {
|
||||
lang.BaseObject
|
||||
codec Codec[io.Reader, V]
|
||||
}
|
||||
)
|
||||
|
||||
func ArrayCodec[V any](codec Codec[io.Reader, V]) Codec[[]byte, []V] {
|
||||
return &arrayCodec[V]{codec: codec}
|
||||
}
|
||||
|
||||
func (a *arrayCodec[V]) encode(v2 []V) []byte {
|
||||
var bs []byte
|
||||
for _, v := range v2 {
|
||||
encode := a.codec.encode(v)
|
||||
all, err := io.ReadAll(encode)
|
||||
if err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
bs = append(bs, all...)
|
||||
}
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
func (a *arrayCodec[V]) decode(v1 []byte) []V {
|
||||
if len(v1) == 0 {
|
||||
return []V{}
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(v1)
|
||||
|
||||
var values []V
|
||||
|
||||
for func() bool {
|
||||
defer recover()
|
||||
|
||||
v := a.codec.decode(reader)
|
||||
values = append(values, v)
|
||||
|
||||
return reader.Len() > 0
|
||||
}() {
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
32
kv/BoolCodec.go
Normal file
32
kv/BoolCodec.go
Normal file
@ -0,0 +1,32 @@
|
||||
package kv
|
||||
|
||||
import "github.com/tursom/GoCollections/lang"
|
||||
|
||||
type (
|
||||
boolCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
TrueBytes = []byte{1}
|
||||
FalseBytes = []byte{0}
|
||||
|
||||
BoolToByteCodec Codec[[]byte, bool] = &boolCodec{}
|
||||
)
|
||||
|
||||
func (b *boolCodec) encode(v2 bool) []byte {
|
||||
if v2 {
|
||||
return TrueBytes
|
||||
} else {
|
||||
return FalseBytes
|
||||
}
|
||||
}
|
||||
|
||||
func (b *boolCodec) decode(v1 []byte) bool {
|
||||
if len(v1) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return v1[0] != 0
|
||||
}
|
26
kv/ChainCodec.go
Normal file
26
kv/ChainCodec.go
Normal file
@ -0,0 +1,26 @@
|
||||
package kv
|
||||
|
||||
import "github.com/tursom/GoCollections/lang"
|
||||
|
||||
type (
|
||||
chainCodec[V1, V2, V3 any] struct {
|
||||
lang.BaseObject
|
||||
codec1 Codec[V2, V3]
|
||||
codec2 Codec[V1, V2]
|
||||
}
|
||||
)
|
||||
|
||||
func ChainCodec[V1, V2, V3 any](codec1 Codec[V2, V3], codec2 Codec[V1, V2]) Codec[V1, V3] {
|
||||
return &chainCodec[V1, V2, V3]{
|
||||
codec1: codec1,
|
||||
codec2: codec2,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *chainCodec[V1, V2, V3]) encode(v2 V3) V1 {
|
||||
return c.codec2.encode(c.codec1.encode(v2))
|
||||
}
|
||||
|
||||
func (c *chainCodec[V1, V2, V3]) decode(v1 V1) V3 {
|
||||
return c.codec1.decode(c.codec2.decode(v1))
|
||||
}
|
28
kv/MapKvs.go
Normal file
28
kv/MapKvs.go
Normal file
@ -0,0 +1,28 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
type (
|
||||
mapKvs struct {
|
||||
lang.BaseObject
|
||||
m map[string][]byte
|
||||
}
|
||||
)
|
||||
|
||||
func MapKvs() Store[string, []byte] {
|
||||
return &mapKvs{
|
||||
m: make(map[string][]byte),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mapKvs) Put(key string, value []byte) exceptions.Exception {
|
||||
m.m[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mapKvs) Get(key string) ([]byte, exceptions.Exception) {
|
||||
return m.m[key], nil
|
||||
}
|
16
kv/MapKvs_test.go
Normal file
16
kv/MapKvs_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_mapKvs(t *testing.T) {
|
||||
kvs := CodecStore(
|
||||
MapKvs(),
|
||||
ByteToStringCodec,
|
||||
ArrayCodec(ChainCodec(StringToByteCodec, LengthFieldCodec)),
|
||||
)
|
||||
_ = kvs.Put([]byte{1}, []string{"hello", "world!"})
|
||||
fmt.Println(kvs.Get([]byte{1}))
|
||||
}
|
235
kv/NumberCodec.go
Normal file
235
kv/NumberCodec.go
Normal file
@ -0,0 +1,235 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
type (
|
||||
int8ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
int16ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
int32ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
int64ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
uint8ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
uint16ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
uint32ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
uint64ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
float32ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
float64ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
complex64ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
complex128ToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
Int8ToByteCodec Codec[[]byte, int8] = &int8ToByteCodec{}
|
||||
Int16ToByteCodec Codec[[]byte, int16] = &int16ToByteCodec{}
|
||||
Int32ToByteCodec Codec[[]byte, int32] = &int32ToByteCodec{}
|
||||
Int64ToByteCodec Codec[[]byte, int64] = &int64ToByteCodec{}
|
||||
Uint8ToByteCodec Codec[[]byte, uint8] = &uint8ToByteCodec{}
|
||||
Uint16ToByteCodec Codec[[]byte, uint16] = &uint16ToByteCodec{}
|
||||
Uint32ToByteCodec Codec[[]byte, uint32] = &uint32ToByteCodec{}
|
||||
Uint64ToByteCodec Codec[[]byte, uint64] = &uint64ToByteCodec{}
|
||||
Float32ToByteCodec Codec[[]byte, float32] = &float32ToByteCodec{}
|
||||
Float64ToByteCodec Codec[[]byte, float64] = &float64ToByteCodec{}
|
||||
Complex64ToByteCodec Codec[[]byte, complex64] = &complex64ToByteCodec{}
|
||||
Complex128ToByteCodec Codec[[]byte, complex128] = &complex128ToByteCodec{}
|
||||
ByteToInt8Codec = InvertCodec[int8, []byte](&int8ToByteCodec{})
|
||||
ByteToInt16Codec = InvertCodec[int16, []byte](&int16ToByteCodec{})
|
||||
ByteToInt32Codec = InvertCodec[int32, []byte](&int32ToByteCodec{})
|
||||
ByteToInt64Codec = InvertCodec[int64, []byte](&int64ToByteCodec{})
|
||||
ByteToUint8Codec = InvertCodec[uint8, []byte](&uint8ToByteCodec{})
|
||||
ByteToUint16Codec = InvertCodec[uint16, []byte](&uint16ToByteCodec{})
|
||||
ByteToUint32Codec = InvertCodec[uint32, []byte](&uint32ToByteCodec{})
|
||||
ByteToUint64Codec = InvertCodec[uint64, []byte](&uint64ToByteCodec{})
|
||||
ByteToFloat32Codec = InvertCodec[float32, []byte](&float32ToByteCodec{})
|
||||
ByteToFloat64Codec = InvertCodec[float64, []byte](&float64ToByteCodec{})
|
||||
ByteToComplex64Codec = InvertCodec[complex64, []byte](&complex64ToByteCodec{})
|
||||
ByteToComplex128Codec = InvertCodec[complex128, []byte](&complex128ToByteCodec{})
|
||||
)
|
||||
|
||||
func (u *int8ToByteCodec) encode(v2 int8) []byte {
|
||||
return []byte{byte(v2)}
|
||||
}
|
||||
|
||||
func (u *int8ToByteCodec) decode(v1 []byte) int8 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int8(v1[0])
|
||||
}
|
||||
|
||||
func (u *int16ToByteCodec) encode(v2 int16) []byte {
|
||||
return binary.BigEndian.AppendUint16(nil, uint16(v2))
|
||||
}
|
||||
|
||||
func (u *int16ToByteCodec) decode(v1 []byte) int16 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int16(binary.BigEndian.Uint16(v1))
|
||||
}
|
||||
|
||||
func (u *int32ToByteCodec) encode(v2 int32) []byte {
|
||||
return binary.BigEndian.AppendUint32(nil, uint32(v2))
|
||||
}
|
||||
|
||||
func (u *int32ToByteCodec) decode(v1 []byte) int32 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int32(binary.BigEndian.Uint32(v1))
|
||||
}
|
||||
|
||||
func (u *int64ToByteCodec) encode(v2 int64) []byte {
|
||||
return binary.BigEndian.AppendUint64(nil, uint64(v2))
|
||||
}
|
||||
|
||||
func (u *int64ToByteCodec) decode(v1 []byte) int64 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int64(binary.BigEndian.Uint64(v1))
|
||||
}
|
||||
|
||||
func (u *uint8ToByteCodec) encode(v2 uint8) []byte {
|
||||
return []byte{v2}
|
||||
}
|
||||
|
||||
func (u *uint8ToByteCodec) decode(v1 []byte) uint8 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return v1[0]
|
||||
}
|
||||
|
||||
func (u *uint16ToByteCodec) encode(v2 uint16) []byte {
|
||||
return binary.BigEndian.AppendUint16(nil, v2)
|
||||
}
|
||||
|
||||
func (u *uint16ToByteCodec) decode(v1 []byte) uint16 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint16(v1)
|
||||
}
|
||||
|
||||
func (u *uint32ToByteCodec) encode(v2 uint32) []byte {
|
||||
return binary.BigEndian.AppendUint32(nil, v2)
|
||||
}
|
||||
|
||||
func (u *uint32ToByteCodec) decode(v1 []byte) uint32 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint32(v1)
|
||||
}
|
||||
|
||||
func (u *uint64ToByteCodec) encode(v2 uint64) []byte {
|
||||
return binary.BigEndian.AppendUint64(nil, v2)
|
||||
}
|
||||
|
||||
func (u *uint64ToByteCodec) decode(v1 []byte) uint64 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint64(v1)
|
||||
}
|
||||
|
||||
func (u *float32ToByteCodec) encode(v2 float32) []byte {
|
||||
return binary.BigEndian.AppendUint32(nil, *(*uint32)(unsafe.Pointer(&v2)))
|
||||
}
|
||||
|
||||
func (u *float32ToByteCodec) decode(v1 []byte) float32 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
u2 := binary.BigEndian.Uint32(v1)
|
||||
return *(*float32)(unsafe.Pointer(&u2))
|
||||
}
|
||||
|
||||
func (u *float64ToByteCodec) encode(v2 float64) []byte {
|
||||
return binary.BigEndian.AppendUint64(nil, *(*uint64)(unsafe.Pointer(&v2)))
|
||||
}
|
||||
|
||||
func (u *float64ToByteCodec) decode(v1 []byte) float64 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
u2 := binary.BigEndian.Uint64(v1)
|
||||
return *(*float64)(unsafe.Pointer(&u2))
|
||||
}
|
||||
|
||||
func (u *complex64ToByteCodec) encode(v2 complex64) []byte {
|
||||
return binary.BigEndian.AppendUint64(nil, *(*uint64)(unsafe.Pointer(&v2)))
|
||||
}
|
||||
|
||||
func (u *complex64ToByteCodec) decode(v1 []byte) complex64 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
u2 := binary.BigEndian.Uint64(v1)
|
||||
return *(*complex64)(unsafe.Pointer(&u2))
|
||||
}
|
||||
|
||||
func (u *complex128ToByteCodec) encode(v2 complex128) []byte {
|
||||
r := real(v2)
|
||||
i := imag(v2)
|
||||
|
||||
bytes := make([]byte, 16)
|
||||
|
||||
binary.BigEndian.PutUint64(bytes[0:], *(*uint64)(unsafe.Pointer(&r)))
|
||||
binary.BigEndian.PutUint64(bytes[8:], *(*uint64)(unsafe.Pointer(&i)))
|
||||
|
||||
return bytes
|
||||
}
|
||||
|
||||
func (u *complex128ToByteCodec) decode(v1 []byte) complex128 {
|
||||
if len(v1) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
r := binary.BigEndian.Uint64(v1[0:])
|
||||
i := binary.BigEndian.Uint64(v1[8:])
|
||||
|
||||
return complex(
|
||||
*(*float64)(unsafe.Pointer(&r)),
|
||||
*(*float64)(unsafe.Pointer(&i)),
|
||||
)
|
||||
}
|
41
kv/ProtoCodec.go
Normal file
41
kv/ProtoCodec.go
Normal file
@ -0,0 +1,41 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type (
|
||||
protoToByteCodec[V proto.Message] struct {
|
||||
lang.BaseObject
|
||||
emptyMessage func() V
|
||||
}
|
||||
)
|
||||
|
||||
func ProtoCodec[V proto.Message](emptyMessage func() V) Codec[[]byte, V] {
|
||||
return &protoToByteCodec[V]{
|
||||
emptyMessage: emptyMessage,
|
||||
}
|
||||
}
|
||||
|
||||
func ProtoDeCodec[V proto.Message](emptyMessage func() V) Codec[V, []byte] {
|
||||
return InvertCodec(ProtoCodec(emptyMessage))
|
||||
}
|
||||
|
||||
func (p *protoToByteCodec[V]) encode(v2 V) []byte {
|
||||
bytes, err := proto.Marshal(v2)
|
||||
if err == nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
return bytes
|
||||
}
|
||||
|
||||
func (p *protoToByteCodec[V]) decode(v1 []byte) V {
|
||||
message := p.emptyMessage()
|
||||
if err := proto.Unmarshal(v1, message); err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
return message
|
||||
}
|
91
kv/ReaderCodec.go
Normal file
91
kv/ReaderCodec.go
Normal file
@ -0,0 +1,91 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
// 不推荐使用
|
||||
|
||||
type (
|
||||
readerCodec[V any] struct {
|
||||
lang.BaseObject
|
||||
codec Codec[[]byte, V]
|
||||
}
|
||||
fixedLengthCodec struct {
|
||||
lang.BaseObject
|
||||
frameLength uint32
|
||||
}
|
||||
lengthFieldCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
LengthFieldCodec Codec[io.Reader, []byte] = &lengthFieldCodec{}
|
||||
)
|
||||
|
||||
func ReaderCodec[V any](codec Codec[[]byte, V]) Codec[io.Reader, V] {
|
||||
return &readerCodec[V]{
|
||||
codec: codec,
|
||||
}
|
||||
}
|
||||
|
||||
func FixedLengthCodec(frameLength uint32) Codec[io.Reader, []byte] {
|
||||
return &fixedLengthCodec{frameLength: frameLength}
|
||||
}
|
||||
|
||||
func (r *readerCodec[V]) encode(v2 V) io.Reader {
|
||||
return bytes.NewReader(r.codec.encode(v2))
|
||||
}
|
||||
|
||||
func (r *readerCodec[V]) decode(v1 io.Reader) V {
|
||||
all, err := io.ReadAll(v1)
|
||||
if err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
return r.codec.decode(all)
|
||||
}
|
||||
|
||||
func (f *fixedLengthCodec) encode(v2 []byte) io.Reader {
|
||||
return bytes.NewReader(v2)
|
||||
}
|
||||
|
||||
func (f *fixedLengthCodec) decode(v1 io.Reader) []byte {
|
||||
bs := make([]byte, f.frameLength)
|
||||
n, err := v1.Read(bs)
|
||||
if err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
return bs[0:n]
|
||||
}
|
||||
|
||||
func (l *lengthFieldCodec) encode(v2 []byte) io.Reader {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
|
||||
_ = binary.Write(buffer, binary.BigEndian, uint32(len(v2)))
|
||||
buffer.Write(v2)
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
func (l *lengthFieldCodec) decode(v1 io.Reader) []byte {
|
||||
var length uint32
|
||||
if err := binary.Read(v1, binary.BigEndian, &length); err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
bs := make([]byte, length)
|
||||
n, err := v1.Read(bs)
|
||||
if err != nil {
|
||||
panic(exceptions.Package(err))
|
||||
}
|
||||
|
||||
return bs[0:n]
|
||||
}
|
26
kv/StringCodec.go
Normal file
26
kv/StringCodec.go
Normal file
@ -0,0 +1,26 @@
|
||||
package kv
|
||||
|
||||
import "github.com/tursom/GoCollections/lang"
|
||||
|
||||
type (
|
||||
stringToByteCodec struct {
|
||||
lang.BaseObject
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
StringToByteCodec Codec[[]byte, string] = &stringToByteCodec{}
|
||||
ByteToStringCodec = InvertCodec[string, []byte](&stringToByteCodec{})
|
||||
)
|
||||
|
||||
func (s *stringToByteCodec) encode(v2 string) []byte {
|
||||
return []byte(v2)
|
||||
}
|
||||
|
||||
func (s *stringToByteCodec) decode(v1 []byte) string {
|
||||
if len(v1) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(v1)
|
||||
}
|
116
kv/codec.go
Normal file
116
kv/codec.go
Normal file
@ -0,0 +1,116 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
type (
|
||||
Codec[V1, V2 any] interface {
|
||||
lang.Object
|
||||
encode(v2 V2) V1
|
||||
decode(v1 V1) V2
|
||||
}
|
||||
|
||||
codecStore[K1, K2, V1, V2 any] struct {
|
||||
lang.BaseObject
|
||||
kvs Store[K1, V1]
|
||||
kCodec Codec[K1, K2]
|
||||
vCodec Codec[V1, V2]
|
||||
}
|
||||
|
||||
kCodecStore[K1, K2, V any] struct {
|
||||
lang.BaseObject
|
||||
kvs Store[K1, V]
|
||||
codec Codec[K1, K2]
|
||||
}
|
||||
|
||||
vCodecStore[K, V1, V2 any] struct {
|
||||
lang.BaseObject
|
||||
kvs Store[K, V1]
|
||||
codec Codec[V1, V2]
|
||||
}
|
||||
|
||||
invertCodec[V1, V2 any] struct {
|
||||
lang.BaseObject
|
||||
codec Codec[V2, V1]
|
||||
}
|
||||
)
|
||||
|
||||
func InvertCodec[V1, V2 any](codec Codec[V2, V1]) Codec[V1, V2] {
|
||||
return &invertCodec[V1, V2]{codec: codec}
|
||||
}
|
||||
|
||||
func CodecStore[K1, K2, V1, V2 any](
|
||||
kvs Store[K1, V1],
|
||||
kCodec Codec[K1, K2],
|
||||
vCodec Codec[V1, V2],
|
||||
) Store[K2, V2] {
|
||||
return &codecStore[K1, K2, V1, V2]{
|
||||
kvs: kvs,
|
||||
kCodec: kCodec,
|
||||
vCodec: vCodec,
|
||||
}
|
||||
}
|
||||
|
||||
func KCodecStore[K1, K2, V any](
|
||||
kvs Store[K1, V],
|
||||
codec Codec[K1, K2],
|
||||
) Store[K2, V] {
|
||||
return &kCodecStore[K1, K2, V]{
|
||||
kvs: kvs,
|
||||
codec: codec,
|
||||
}
|
||||
}
|
||||
|
||||
func VCodecStore[K, V1, V2 any](
|
||||
kvs Store[K, V1],
|
||||
codec Codec[V1, V2],
|
||||
) Store[K, V2] {
|
||||
return &vCodecStore[K, V1, V2]{
|
||||
kvs: kvs,
|
||||
codec: codec,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *codecStore[K1, K2, V1, V2]) Put(key K2, value V2) exceptions.Exception {
|
||||
return c.kvs.Put(c.kCodec.encode(key), c.vCodec.encode(value))
|
||||
}
|
||||
|
||||
func (c *codecStore[K1, K2, V1, V2]) Get(key K2) (V2, exceptions.Exception) {
|
||||
value, exception := c.kvs.Get(c.kCodec.encode(key))
|
||||
if exception != nil {
|
||||
return lang.Nil[V2](), exception
|
||||
}
|
||||
|
||||
return c.vCodec.decode(value), nil
|
||||
}
|
||||
|
||||
func (c *kCodecStore[K1, K2, V]) Put(key K2, value V) exceptions.Exception {
|
||||
return c.kvs.Put(c.codec.encode(key), value)
|
||||
}
|
||||
|
||||
func (c *kCodecStore[K1, K2, V]) Get(key K2) (V, exceptions.Exception) {
|
||||
return c.kvs.Get(c.codec.encode(key))
|
||||
}
|
||||
|
||||
func (c *vCodecStore[K, V1, V2]) Put(key K, value V2) exceptions.Exception {
|
||||
return c.kvs.Put(key, c.codec.encode(value))
|
||||
}
|
||||
|
||||
func (c *vCodecStore[K, V1, V2]) Get(key K) (V2, exceptions.Exception) {
|
||||
get, exception := c.kvs.Get(key)
|
||||
if exception != nil {
|
||||
return lang.Nil[V2](), exception
|
||||
}
|
||||
|
||||
return c.codec.decode(get), nil
|
||||
}
|
||||
|
||||
func (i *invertCodec[V1, V2]) encode(v2 V2) V1 {
|
||||
return i.codec.decode(v2)
|
||||
}
|
||||
|
||||
func (i *invertCodec[V1, V2]) decode(v1 V1) V2 {
|
||||
return i.codec.encode(v1)
|
||||
}
|
14
kv/kvs.go
Normal file
14
kv/kvs.go
Normal file
@ -0,0 +1,14 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
)
|
||||
|
||||
type (
|
||||
Store[K, V any] interface {
|
||||
lang.Object
|
||||
Put(key K, value V) exceptions.Exception
|
||||
Get(key K) (V, exceptions.Exception)
|
||||
}
|
||||
)
|
37
leveldb/leveldb.go
Normal file
37
leveldb/leveldb.go
Normal file
@ -0,0 +1,37 @@
|
||||
package leveldb
|
||||
|
||||
import (
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
|
||||
"kvs/kv"
|
||||
)
|
||||
|
||||
type (
|
||||
leveldbKVS struct {
|
||||
lang.BaseObject
|
||||
db *leveldb.DB
|
||||
}
|
||||
)
|
||||
|
||||
func New(db *leveldb.DB) kv.Store[[]byte, []byte] {
|
||||
return &leveldbKVS{db: db}
|
||||
}
|
||||
|
||||
func (l *leveldbKVS) Put(key []byte, value []byte) exceptions.Exception {
|
||||
if err := l.db.Put(key, value, nil); err != nil {
|
||||
return exceptions.Package(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *leveldbKVS) Get(key []byte) ([]byte, exceptions.Exception) {
|
||||
value, err := l.db.Get(key, nil)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
27
leveldb/leveldb_test.go
Normal file
27
leveldb/leveldb_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
package leveldb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
|
||||
"kvs/kv"
|
||||
)
|
||||
|
||||
func Test_leveldbKVS(t *testing.T) {
|
||||
db, err := leveldb.OpenFile("test", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s := kv.CodecStore(New(db), kv.StringToByteCodec, kv.StringToByteCodec)
|
||||
|
||||
if err := s.Put("hello", "world!"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value, exception := s.Get("hello")
|
||||
if exception != nil || value != "world!" {
|
||||
t.Fatal(value, exception)
|
||||
}
|
||||
}
|
11
pipe/pipe.go
Normal file
11
pipe/pipe.go
Normal file
@ -0,0 +1,11 @@
|
||||
package pipe
|
||||
|
||||
import "github.com/tursom/GoCollections/lang"
|
||||
|
||||
type (
|
||||
PipelineHandler[V1, V2 any] interface {
|
||||
lang.Object
|
||||
encode1(input []V1) []V2
|
||||
encode2(input []V2) []V1
|
||||
}
|
||||
)
|
90
sqlite/sqlite.go
Normal file
90
sqlite/sqlite.go
Normal file
@ -0,0 +1,90 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
|
||||
"kvs/kv"
|
||||
)
|
||||
|
||||
type (
|
||||
sqliteKVS struct {
|
||||
lang.BaseObject
|
||||
db *sql.DB
|
||||
table string
|
||||
}
|
||||
)
|
||||
|
||||
func New(db *sql.DB, table string) (kv.Store[[]byte, []byte], exceptions.Exception) {
|
||||
kvs := &sqliteKVS{
|
||||
db: db,
|
||||
table: table,
|
||||
}
|
||||
if err := kvs.createTable(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return kvs, nil
|
||||
}
|
||||
|
||||
func (s *sqliteKVS) createTable() exceptions.Exception {
|
||||
if _, err := s.db.Exec("create table if not exists " + s.table + " (" +
|
||||
"k blob primary key not null," +
|
||||
"v blob" +
|
||||
")"); err != nil {
|
||||
return exceptions.Package(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqliteKVS) Get(key []byte) ([]byte, exceptions.Exception) {
|
||||
rows, err := s.db.Query("select v from "+s.table+" where k = ?", key)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var data []byte
|
||||
err = rows.Scan(&data)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (s *sqliteKVS) Put(key []byte, value []byte) exceptions.Exception {
|
||||
if value == nil {
|
||||
value = []byte{}
|
||||
}
|
||||
|
||||
exec, err := s.db.Exec("update "+s.table+" set v=? where k=?", value, key)
|
||||
if err != nil {
|
||||
return exceptions.Package(err)
|
||||
}
|
||||
|
||||
affected, err := exec.RowsAffected()
|
||||
if err != nil {
|
||||
return exceptions.Package(err)
|
||||
}
|
||||
|
||||
if affected != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err = s.db.Exec("insert into "+s.table+" (k,v) values (?,?)", key, value); err != nil {
|
||||
return exceptions.Package(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
30
sqlite/sqlite_test.go
Normal file
30
sqlite/sqlite_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
|
||||
"kvs/kv"
|
||||
)
|
||||
|
||||
func Test_sqliteKVS(t *testing.T) {
|
||||
db := exceptions.Exec2r1(sql.Open, "sqlite3", ":memory:")
|
||||
s, exception := New(db, "kv")
|
||||
if exception != nil {
|
||||
t.Fatal(exception)
|
||||
}
|
||||
|
||||
skvs := kv.CodecStore(s, kv.StringToByteCodec, kv.StringToByteCodec)
|
||||
|
||||
if err := skvs.Put("hello", "world!"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value, exception := skvs.Get("hello")
|
||||
if exception != nil || value != "world!" {
|
||||
t.Fatal(value, exception)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user