44 "bytes"
55 "encoding/binary"
66 "io"
7+ "sync"
78
89 "github.com/HyperloopUPV-H8/h9-backend/pkg/abstraction"
910 "github.com/rs/zerolog"
@@ -17,7 +18,8 @@ type Encoder struct {
1718 idToEncoder map [abstraction.PacketId ]PacketEncoder
1819 endianness binary.ByteOrder
1920
20- logger zerolog.Logger
21+ logger zerolog.Logger
22+ bufPool sync.Pool
2123}
2224
2325// TODO: improve constructor
@@ -28,6 +30,9 @@ func NewEncoder(endianness binary.ByteOrder, baseLogger zerolog.Logger) *Encoder
2830 endianness : endianness ,
2931
3032 logger : baseLogger ,
33+ bufPool : sync.Pool {
34+ New : func () any { return new (bytes.Buffer ) },
35+ },
3136 }
3237}
3338
@@ -37,23 +42,41 @@ func (encoder *Encoder) SetPacketEncoder(id abstraction.PacketId, enc PacketEnco
3742 encoder .logger .Trace ().Uint16 ("id" , uint16 (id )).Type ("encoder" , enc ).Msg ("set encoder" )
3843}
3944
40- // Encode encodes the provided packet into a byte slice, returning any errors
41- func (encoder * Encoder ) Encode (packet abstraction.Packet ) ([]byte , error ) {
45+ // Encode encodes the provided packet into a pooled buffer. Callers must release
46+ // the buffer via ReleaseBuffer once they are done using the returned data.
47+ func (encoder * Encoder ) Encode (packet abstraction.Packet ) (* bytes.Buffer , error ) {
4248 enc , ok := encoder .idToEncoder [packet .Id ()]
4349 if ! ok {
4450 encoder .logger .Warn ().Uint16 ("id" , uint16 (packet .Id ())).Msg ("no encoder set" )
4551 return nil , ErrUnexpectedId {Id : packet .Id ()}
4652 }
4753
48- buffer := new (bytes.Buffer )
54+ bufferAny := encoder .bufPool .Get ()
55+ buffer := bufferAny .(* bytes.Buffer )
56+ buffer .Reset ()
4957
5058 err := binary .Write (buffer , encoder .endianness , packet .Id ())
5159 if err != nil {
5260 encoder .logger .Error ().Stack ().Err (err ).Uint16 ("id" , uint16 (packet .Id ())).Msg ("buffering id" )
53- return buffer .Bytes (), err
61+ encoder .ReleaseBuffer (buffer )
62+ return nil , err
5463 }
5564
5665 encoder .logger .Debug ().Uint16 ("id" , uint16 (packet .Id ())).Type ("encoder" , enc ).Msg ("encoding" )
5766 err = enc .Encode (packet , buffer )
58- return buffer .Bytes (), err
67+ if err != nil {
68+ encoder .ReleaseBuffer (buffer )
69+ return nil , err
70+ }
71+
72+ return buffer , nil
73+ }
74+
75+ // ReleaseBuffer returns a buffer obtained from Encode back to the pool.
76+ func (encoder * Encoder ) ReleaseBuffer (buffer * bytes.Buffer ) {
77+ if buffer == nil {
78+ return
79+ }
80+ buffer .Reset ()
81+ encoder .bufPool .Put (buffer )
5982}
0 commit comments