Newer
Older
// Package wsjson provides helpers for reading and writing JSON messages.
import (
"context"
"encoding/json"
"gfx.cafe/open/websocket"
"gfx.cafe/open/websocket/internal/bpool"
"gfx.cafe/open/websocket/internal/errd"
// Read reads a JSON message from c into v.
// It will reuse buffers in between calls to avoid allocations.
func Read(ctx context.Context, c *websocket.Conn, v interface{}) error {
func read(ctx context.Context, c *websocket.Conn, v interface{}) (err error) {
defer errd.Wrap(&err, "failed to read JSON message")
if err != nil {
return err
}
_, err = b.ReadFrom(r)
if err != nil {
return err
}
err = json.Unmarshal(b.Bytes(), v)
c.Close(websocket.StatusInvalidFramePayloadData, "failed to unmarshal JSON")
return fmt.Errorf("failed to unmarshal JSON: %w", err)
// Write writes the JSON message v to c.
// It will reuse buffers in between calls to avoid allocations.
func Write(ctx context.Context, c *websocket.Conn, v interface{}) error {
func write(ctx context.Context, c *websocket.Conn, v interface{}) (err error) {
defer errd.Wrap(&err, "failed to write JSON message")
// json.Marshal cannot reuse buffers between calls as it has to return
// a copy of the byte slice but Encoder does as it directly writes to w.
err = json.NewEncoder(util.WriterFunc(func(p []byte) (int, error) {
err := c.Write(ctx, websocket.MessageText, p)
if err != nil {
return 0, err
}
return len(p), nil
})).Encode(v)
return fmt.Errorf("failed to marshal JSON: %w", err)