Skip to content

Commit

Permalink
add some feature to proto
Browse files Browse the repository at this point in the history
  • Loading branch information
PotatoCloud committed Aug 1, 2023
1 parent 85bf692 commit 11e6e23
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 7 deletions.
10 changes: 8 additions & 2 deletions example/simple-chat/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
ProtoQuitRoom
ProtoSendMessage

ProtoRecvMessage = iota + 1000
ProtoRecvMessage = iota - ProtoSendMessage + 1000
)

type Proto struct {
Expand Down Expand Up @@ -123,9 +123,15 @@ func (s *service) sendMessage(req *proto.Request[Proto]) {

func main() {

engine := proto.New[Proto, ProtoType](func() proto.Proto[Proto, ProtoType] {
instancePool := proto.NewInstancePool[Proto, ProtoType](func() proto.Proto[Proto, ProtoType] {
return new(Proto)
})

engine := proto.New[Proto, ProtoType](instancePool.Alloc)
engine.RegisterDestroyProto(func(_ *qWebsocket.HandlerParams, proto proto.Proto[Proto, ProtoType]) {
instancePool.Free(proto)
})

s := &service{}

engine.Register(ProtoJoinRoom, s.joinRoom)
Expand Down
16 changes: 16 additions & 0 deletions proto/codec_xml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package proto

import (
"encoding/xml"
"io"
)

type CodecXML[T any, K comparable] struct{}

func (k CodecXML[T, K]) Marshal(w io.Writer, val Proto[T, K]) error {
return xml.NewEncoder(w).Encode(val.Value())
}

func (k CodecXML[T, K]) Unmarshal(r io.Reader, ptr Proto[T, K]) error {
return xml.NewDecoder(r).Decode(ptr.Self())
}
21 changes: 17 additions & 4 deletions proto/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import (
"log"
)

type HandlerFunc[T any] func(*Request[T])
type (
HandlerFunc[T any] func(*Request[T])
NewProtoFunc[T any, K comparable] func() Proto[T, K]
DestroyProtoFunc[T any, K comparable] func(params *qWebsocket.HandlerParams, proto Proto[T, K])
)

type Engine[T any, K comparable] struct {
codec Codec[T, K]
handlers map[K]HandlerFunc[T]
newProto func() Proto[T, K]
codec Codec[T, K]
handlers map[K]HandlerFunc[T]
newProto NewProtoFunc[T, K]
destroyProto DestroyProtoFunc[T, K]
}

// Handler
Expand All @@ -20,6 +25,10 @@ type Engine[T any, K comparable] struct {
func (e *Engine[T, K]) Handler(params *qWebsocket.HandlerParams) {
proto := e.newProto()

if e.destroyProto != nil {
defer e.destroyProto(params, proto)
}

if err := e.codec.Unmarshal(bytes.NewReader(params.Request), proto); err != nil {
log.Println("Proto engine codec error:", err)
return
Expand All @@ -46,3 +55,7 @@ func (e *Engine[T, K]) Register(key K, handler HandlerFunc[T]) {
func (e *Engine[T, K]) RegisterCodec(codec Codec[T, K]) {
e.codec = codec
}

func (e *Engine[T, K]) RegisterDestroyProto(handler DestroyProtoFunc[T, K]) {
e.destroyProto = handler
}
27 changes: 27 additions & 0 deletions proto/instance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package proto

import "sync"

type InstancePool[T any, K comparable] struct {
pool sync.Pool
}

func (k *InstancePool[T, K]) Alloc() Proto[T, K] {
return k.pool.Get().(Proto[T, K])
}

func (k *InstancePool[T, K]) Free(proto Proto[T, K]) {
// if Proto impl Resetter interface
if free, ok := proto.(Resetter); ok {
free.Reset()
}
k.pool.Put(proto)
}

func NewInstancePool[T any, K comparable](newProto func() Proto[T, K]) *InstancePool[T, K] {
return &InstancePool[T, K]{
pool: sync.Pool{
New: func() any { return newProto() },
},
}
}
28 changes: 27 additions & 1 deletion proto/proto.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
package proto

type Proto[T any, K comparable] interface {
// Key realizes the value that returns Proto can be comparable
//
// case:
// type Proto struct {
// Type uint32
// Message string
// }
//
// func (p *Proto) Key() uint32 { return p.Type }
Key() K
// Value return a copy of itself
//
// case:
// func (p *Proto) Value() Proto { return *p }
Value() T
// Self return a pointer of itself
//
// case:
// func (p *Proto) Self() *Proto { return p }
Self() *T
}

func New[T any, K comparable](newProto func() Proto[T, K]) *Engine[T, K] {
type Resetter interface {
Reset()
}

// New a proto engine instance
//
// args
//
// - newProto should be return a Proto instance
func New[T any, K comparable](newProto NewProtoFunc[T, K]) *Engine[T, K] {
return &Engine[T, K]{
codec: &CodecJSON[T, K]{},
handlers: make(map[K]HandlerFunc[T]),
Expand Down

0 comments on commit 11e6e23

Please sign in to comment.