diff --git a/commands/channelmarshaler.go b/commands/channelmarshaler.go new file mode 100644 index 0000000000000000000000000000000000000000..826b32eabe30e33aa3b69cc556da5d56fb51e38a --- /dev/null +++ b/commands/channelmarshaler.go @@ -0,0 +1,34 @@ +package commands + +import "io" + +type ChannelMarshaler struct { + Channel <-chan interface{} + Marshaler func(interface{}) (io.Reader, error) + + reader io.Reader +} + +func (cr *ChannelMarshaler) Read(p []byte) (int, error) { + if cr.reader == nil { + val, more := <-cr.Channel + if !more { + return 0, io.EOF + } + + r, err := cr.Marshaler(val) + if err != nil { + return 0, err + } + cr.reader = r + } + + n, err := cr.reader.Read(p) + if err != nil && err != io.EOF { + return n, err + } + if n == 0 { + cr.reader = nil + } + return n, nil +} diff --git a/commands/response.go b/commands/response.go index f776605b3cf570a45872e920fa34e76c75e7d122..4dd717235e5739ff2598a0b31f2be8eeb9ad5854 100644 --- a/commands/response.go +++ b/commands/response.go @@ -40,20 +40,30 @@ const ( // TODO: support more encoding types ) +func marshalJson(value interface{}) (io.Reader, error) { + b, err := json.MarshalIndent(value, "", " ") + if err != nil { + return nil, err + } + return bytes.NewReader(b), nil +} + var marshallers = map[EncodingType]Marshaler{ JSON: func(res Response) (io.Reader, error) { + if ch, ok := res.Output().(chan interface{}); ok { + return &ChannelMarshaler{ + Channel: ch, + Marshaler: marshalJson, + }, nil + } + var value interface{} if res.Error() != nil { value = res.Error() } else { value = res.Output() } - - b, err := json.MarshalIndent(value, "", " ") - if err != nil { - return nil, err - } - return bytes.NewReader(b), nil + return marshalJson(value) }, XML: func(res Response) (io.Reader, error) { var value interface{}