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 }