github.com/shogo-ma/goa@v1.3.1/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 return dec.pBuf.Unmarshal(msg) 58 } 59 60 // Reset stores the new reader and resets its bytes.Buffer and proto.Buffer 61 func (dec *ProtoDecoder) Reset(r io.Reader) { 62 dec.pBuf.Reset() 63 dec.bBuf.Reset() 64 dec.r = r 65 } 66 67 // NewEncoder returns a new proto.Encoder that satisfies goa.Encoder 68 func NewEncoder(w io.Writer) goa.Encoder { 69 return &ProtoEncoder{ 70 pBuf: proto.NewBuffer(nil), 71 w: w, 72 } 73 } 74 75 // Encode marshals a proto.Message and writes it to an io.Writer 76 func (enc *ProtoEncoder) Encode(v interface{}) error { 77 msg, ok := v.(proto.Message) 78 if !ok { 79 return errors.New("Cannot encode struct that doesn't implement proto.Message") 80 } 81 82 var err error 83 84 // derekperkins TODO: pipe marshal directly to writer 85 if err = enc.pBuf.Marshal(msg); err != nil { 86 return err 87 } 88 89 if _, err = enc.w.Write(enc.pBuf.Bytes()); err != nil { 90 return err 91 } 92 return nil 93 } 94 95 // Reset stores the new writer and resets its proto.Buffer 96 func (enc *ProtoEncoder) Reset(w io.Writer) { 97 enc.pBuf.Reset() 98 enc.w = w 99 }