Skip to content

Instantly share code, notes, and snippets.

@belak
Last active December 16, 2015 06:49
Show Gist options
  • Select an option

  • Save belak/5394160 to your computer and use it in GitHub Desktop.

Select an option

Save belak/5394160 to your computer and use it in GitHub Desktop.
package main
// NOTE: This implements the following protocol:
// https://github.com/turn/json-over-tcp
// This was done for chunking reasons
// Darn you TCP!
import (
"encoding/binary"
"encoding/json"
"errors"
"io"
)
var magic uint16 = 206
type Encoder interface {
Encode(interface{}) error
}
type Decoder interface {
Decode(interface{}) error
}
type JotEncoder struct {
w io.Writer
}
type JotDecoder struct {
r io.Reader
}
func NewEncoder(w io.Writer) *JotEncoder {
return &JotEncoder{w: w}
}
func NewDecoder(r io.Reader) *JotDecoder {
return &JotDecoder{r: r}
}
func (b *JotEncoder) Encode(d interface{}) error {
data, err := json.Marshal(d)
if err != nil {
return err
}
err = binary.Write(b.w, binary.LittleEndian, magic)
if err != nil {
return err
}
size := len(data)
err = binary.Write(b.w, binary.LittleEndian, uint32(size))
if err != nil {
return err
}
written, err := b.w.Write(data)
if err != nil {
return err
}
return nil
}
func (b *JotDecoder) Decode(d interface{}) error {
var magic_in uint16
err := binary.Read(b.r, binary.LittleEndian, &magic_in)
if err != nil {
return err
} else if magic_in != magic {
return errors.New("magic number didn't match")
}
var size uint32
err = binary.Read(b.r, binary.LittleEndian, &size)
if err != nil {
return err
}
data := make([]byte, size)
read, err := io.ReadFull(b.r, data)
if err != nil {
return err
} else if uint32(read) != size {
return errors.New("read != size")
}
err = json.Unmarshal(data, d)
if err != nil {
return err
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment