github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/encoding/gogoprotobuf/encoding.go (about)

     1  package gogoprotobuf
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  
     8  	"github.com/goadesign/goa"
     9  	"github.com/gogo/protobuf/proto"
    10  )
    11  
    12  // Enforce that codec.Decoder satisfies goa.ResettableDecoder at compile time
    13  var (
    14  	_ goa.ResettableDecoder = (*ProtoDecoder)(nil)
    15  	_ goa.ResettableEncoder = (*ProtoEncoder)(nil)
    16  )
    17  
    18  type (
    19  	// ProtoDecoder stores state between Reset and Decode
    20  	ProtoDecoder struct {
    21  		pBuf *proto.Buffer
    22  		bBuf *bytes.Buffer
    23  		r    io.Reader
    24  	}
    25  
    26  	// ProtoEncoder stores state between Reset and Encode
    27  	ProtoEncoder struct {
    28  		pBuf *proto.Buffer
    29  		w    io.Writer
    30  	}
    31  )
    32  
    33  // NewDecoder returns a new proto.Decoder that satisfies goa.Decoder
    34  func NewDecoder(r io.Reader) goa.Decoder {
    35  	return &ProtoDecoder{
    36  		pBuf: proto.NewBuffer(nil),
    37  		bBuf: &bytes.Buffer{},
    38  		r:    r,
    39  	}
    40  }
    41  
    42  // Decode unmarshals an io.Reader into proto.Message v
    43  func (dec *ProtoDecoder) Decode(v interface{}) error {
    44  	msg, ok := v.(proto.Message)
    45  	if !ok {
    46  		return errors.New("Cannot decode into struct that doesn't implement proto.Message")
    47  	}
    48  
    49  	var err error
    50  
    51  	// derekperkins TODO: pipe reader directly to proto.Buffer
    52  	if _, err = dec.bBuf.ReadFrom(dec.r); err != nil {
    53  		return err
    54  	}
    55  	dec.pBuf.SetBuf(dec.bBuf.Bytes())
    56  
    57  	if err = dec.pBuf.Unmarshal(msg); err != nil {
    58  		return err
    59  	}
    60  	return nil
    61  }
    62  
    63  // Reset stores the new reader and resets its bytes.Buffer and proto.Buffer
    64  func (dec *ProtoDecoder) Reset(r io.Reader) {
    65  	dec.pBuf.Reset()
    66  	dec.bBuf.Reset()
    67  	dec.r = r
    68  }
    69  
    70  // NewEncoder returns a new proto.Encoder that satisfies goa.Encoder
    71  func NewEncoder(w io.Writer) goa.Encoder {
    72  	return &ProtoEncoder{
    73  		pBuf: proto.NewBuffer(nil),
    74  		w:    w,
    75  	}
    76  }
    77  
    78  // Encode marshals a proto.Message and writes it to an io.Writer
    79  func (enc *ProtoEncoder) Encode(v interface{}) error {
    80  	msg, ok := v.(proto.Message)
    81  	if !ok {
    82  		return errors.New("Cannot encode struct that doesn't implement proto.Message")
    83  	}
    84  
    85  	var err error
    86  
    87  	// derekperkins TODO: pipe marshal directly to writer
    88  	if err = enc.pBuf.Marshal(msg); err != nil {
    89  		return err
    90  	}
    91  
    92  	if _, err = enc.w.Write(enc.pBuf.Bytes()); err != nil {
    93  		return err
    94  	}
    95  	return nil
    96  }
    97  
    98  // Reset stores the new writer and resets its proto.Buffer
    99  func (enc *ProtoEncoder) Reset(w io.Writer) {
   100  	enc.pBuf.Reset()
   101  	enc.w = w
   102  }