Skip to content

Commit

Permalink
Merge pull request #225 from saeid-a/feat/zset-ZAdd
Browse files Browse the repository at this point in the history
Feat/zset z add(#139)
  • Loading branch information
qishenonly authored Jul 22, 2023
2 parents 759424f + 09b3aea commit 72a24f4
Show file tree
Hide file tree
Showing 4 changed files with 2,643 additions and 16 deletions.
190 changes: 174 additions & 16 deletions lib/encoding/messagepack.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,189 @@ package encoding

import (
"bytes"
"errors"
"github.com/hashicorp/go-msgpack/codec"
"reflect"
)

// EncodeMessagePack is a function that encodes a given message using MessagePack serialization.
// It takes an interface{} parameter representing the message and returns the encoded byte slice and an error.
func EncodeMessagePack(msg interface{}) ([]byte, error) {
var b []byte
var mph codec.MsgpackHandle
h := &mph
enc := codec.NewEncoderBytes(&b, h) // Create a new encoder with the provided message and MessagePack handle
// MessagePackCodec struct, holds references to MessagePack handler and byte slice,
// along with Encoder and Decoder, and a typeMap for storing reflect.Type
type MessagePackCodec struct {
MsgPack *codec.MsgpackHandle
b *[]byte
enc *codec.Encoder
dec *codec.Decoder
}

// MessagePackCodecEncoder struct derives from MessagePackCodec
// it manages IDs and counts of the encoded objects.
type MessagePackCodecEncoder struct {
MessagePackCodec // Embedded MessagePackCodec
}

// MessagePackCodecDecoder struct, holds a reference to a MessagePackCodec instance.
type MessagePackCodecDecoder struct {
*MessagePackCodec
}

err := enc.Encode(msg) // Encode the message using the encoder
// NewMsgPackHandle is a helper function to create a new instance of MsgpackHandle
func NewMsgPackHandle() *codec.MsgpackHandle {
return &codec.MsgpackHandle{}
}

// InitMessagePack function initializes MessagePackCodec struct and returns it.
func InitMessagePack() MessagePackCodec {
return MessagePackCodec{
MsgPack: NewMsgPackHandle(),
}
}

// NewMessagePackEncoder function creates new MessagePackCodecEncoder and initializes it.
func NewMessagePackEncoder() *MessagePackCodecEncoder {
msgPack := NewMsgPackHandle()
b := make([]byte, 0)
return &MessagePackCodecEncoder{
MessagePackCodec: MessagePackCodec{
MsgPack: msgPack,
b: &b,
enc: codec.NewEncoderBytes(&b, msgPack),
},
}
}

// NewMessagePackDecoder function takes in a byte slice, and returns a pointer to newly created
// and initialized MessagePackCodecDecoder
func NewMessagePackDecoder(b []byte) *MessagePackCodecDecoder {
msgPack := NewMsgPackHandle()
return &MessagePackCodecDecoder{
MessagePackCodec: &MessagePackCodec{
MsgPack: msgPack,
b: &b,
dec: codec.NewDecoderBytes(b, msgPack),
},
}
}

// Encode method for MessagePackCodec. It encodes the input value into a byte slice using MessagePack.
// Returns encoded byte slice or error.
func (m *MessagePackCodec) Encode(msg interface{}) ([]byte, error) {
var b []byte
err := codec.NewEncoderBytes(&b, m.MsgPack).Encode(msg)
if err != nil {
return nil, err
}
return b, nil // Return the encoded byte slice
return b, nil
}

// Encode is a method for MessagePackCodecEncoder.
// It takes in msg of type interface{} as input, that is to be encoded.
// Returns an error if encountered during encoding.
func (m *MessagePackCodecEncoder) Encode(msg interface{}) error {
return m.enc.Encode(msg)
}

// Bytes is a method for MessagePackCodecEncoder.
// It returns a byte slice pointer b.
func (m *MessagePackCodecEncoder) Bytes() []byte {
return *m.b
}

// Decode is a method on MessagePackCodecDecoder that decodes MessagePack data
// into the provided interface; returns an error if any decoding issues occur.
func (m *MessagePackCodecDecoder) Decode(msg interface{}) error {
if m.dec == nil {
return errors.New("decoder not initialized")
}
return m.dec.Decode(msg)
}

// Decode on MessagePackCodec type, using a byte slice as input.
func (m *MessagePackCodec) Decode(in []byte, out interface{}) error {
// Create new decoder using the byte slice and MessagePack handle.
dec := codec.NewDecoderBytes(in, m.MsgPack)

// Attempt to decode the byte slice into the desired output structure.
return dec.Decode(out)
}

// AddExtension method allows for setting custom encoders/decoders for specific reflect.Types.
func (m *MessagePackCodec) AddExtension(
t reflect.Type,
id byte,
encoder func(reflect.Value) ([]byte, error),
decoder func(reflect.Value, []byte) error) error {

return m.MsgPack.AddExt(t, id, encoder, decoder)
}

// EncodeMessagePack function encodes a given object into MessagePack format.
func EncodeMessagePack(msg interface{}) ([]byte, error) {
// Directly initialize the byte slice and encoder.
b := make([]byte, 0)
enc := codec.NewEncoderBytes(&b, NewMsgPackHandle())

// Attempt to encode the message.
if err := enc.Encode(msg); err != nil {
return nil, err
}

// Return the encoded byte slice.
return b, nil
}

// DecodeMessagePack is a function that decodes a given byte slice using MessagePack deserialization.
// It takes an input byte slice and an interface{} representing the output structure for the deserialized message.
// It returns an error if the decoding process fails.
// DecodeMessagePack function decodes a byte slice of MessagePack data into a given object.
func DecodeMessagePack(in []byte, out interface{}) error {
buf := bytes.NewBuffer(in) // Create a new buffer with the input byte slice
mph := codec.MsgpackHandle{}
dev := codec.NewDecoder(buf, &mph) // Create a new decoder with the buffer and MessagePack handle
dec := codec.NewDecoder(bytes.NewBuffer(in), NewMsgPackHandle())
return dec.Decode(out)
}

// EncodeString Functions for encoding and decoding strings to and from byte slices.
func EncodeString(s string) ([]byte, error) {
// Check if string length is within correct bounds.
if len(s) > 0x7F {
return nil, errors.New("invalid string length")
}

// Create a byte slice of appropriate length.
b := make([]byte, len(s)+1)
b[0] = byte(len(s))

// Copy the string into the byte slice.
copy(b[1:], s)

// Return the byte slice.
return b, nil
}

/*
DecodeString converts an input byte slice into a string.
Arguments:
b: Input byte slice to be decoded.
Returns:
- Integer: Length of byte representation of the string.
- String: Decoded string.
- Error: 'invalid length' if slice is empty or insufficient length, else nil.
The function reads the first byte as string length (l), creates a slice of length l and returns the formed string.
*/
func DecodeString(b []byte) (int, string, error) {
// Check that byte slice is not empty.
if len(b) == 0 {
return 0, "", errors.New("invalid length")
}

// Determine the length of the string.
l := int(b[0])
if len(b) < (l + 1) {
return 0, "", errors.New("invalid length")
}

// Create a byte slice of the appropriate length and copy the string into it.
s := make([]byte, l)
copy(s, b[1:l+1])

return dev.Decode(out) // Decode the byte slice into the provided output structure
// Return the length of the string and the string itself.
return l + 1, string(s), nil
}
Loading

0 comments on commit 72a24f4

Please sign in to comment.