...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package runtime
16
17 import (
18 "bytes"
19 "encoding"
20 "errors"
21 "fmt"
22 "io"
23 "reflect"
24
25 "github.com/go-openapi/swag"
26 )
27
28 func defaultCloser() error { return nil }
29
30 type byteStreamOpt func(opts *byteStreamOpts)
31
32
33 func ClosesStream(opts *byteStreamOpts) {
34 opts.Close = true
35 }
36
37 type byteStreamOpts struct {
38 Close bool
39 }
40
41
42
43
44
45
46
47
48
49
50
51 func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
52 var vals byteStreamOpts
53 for _, opt := range opts {
54 opt(&vals)
55 }
56
57 return ConsumerFunc(func(reader io.Reader, data interface{}) error {
58 if reader == nil {
59 return errors.New("ByteStreamConsumer requires a reader")
60 }
61 if data == nil {
62 return errors.New("nil destination for ByteStreamConsumer")
63 }
64
65 closer := defaultCloser
66 if vals.Close {
67 if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
68 closer = cl.Close
69 }
70 }
71 defer func() {
72 _ = closer()
73 }()
74
75 if readerFrom, isReaderFrom := data.(io.ReaderFrom); isReaderFrom {
76 _, err := readerFrom.ReadFrom(reader)
77 return err
78 }
79
80 if writer, isDataWriter := data.(io.Writer); isDataWriter {
81 _, err := io.Copy(writer, reader)
82 return err
83 }
84
85
86 var buf bytes.Buffer
87 _, err := buf.ReadFrom(reader)
88 if err != nil {
89 return err
90 }
91 b := buf.Bytes()
92
93 switch destinationPointer := data.(type) {
94 case encoding.BinaryUnmarshaler:
95 return destinationPointer.UnmarshalBinary(b)
96 case *any:
97 switch (*destinationPointer).(type) {
98 case string:
99 *destinationPointer = string(b)
100
101 return nil
102
103 case []byte:
104 *destinationPointer = b
105
106 return nil
107 }
108 default:
109
110 if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
111 return errors.New("destination must be a pointer")
112 }
113
114 v := reflect.Indirect(reflect.ValueOf(data))
115 t := v.Type()
116
117 switch {
118 case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
119 v.SetBytes(b)
120 return nil
121
122 case t.Kind() == reflect.String:
123 v.SetString(string(b))
124 return nil
125 }
126 }
127
128 return fmt.Errorf("%v (%T) is not supported by the ByteStreamConsumer, %s",
129 data, data, "can be resolved by supporting Writer/BinaryUnmarshaler interface")
130 })
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145 func ByteStreamProducer(opts ...byteStreamOpt) Producer {
146 var vals byteStreamOpts
147 for _, opt := range opts {
148 opt(&vals)
149 }
150
151 return ProducerFunc(func(writer io.Writer, data interface{}) error {
152 if writer == nil {
153 return errors.New("ByteStreamProducer requires a writer")
154 }
155 if data == nil {
156 return errors.New("nil data for ByteStreamProducer")
157 }
158
159 closer := defaultCloser
160 if vals.Close {
161 if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
162 closer = cl.Close
163 }
164 }
165 defer func() {
166 _ = closer()
167 }()
168
169 if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
170 defer rc.Close()
171 }
172
173 switch origin := data.(type) {
174 case io.WriterTo:
175 _, err := origin.WriteTo(writer)
176 return err
177
178 case io.Reader:
179 _, err := io.Copy(writer, origin)
180 return err
181
182 case encoding.BinaryMarshaler:
183 bytes, err := origin.MarshalBinary()
184 if err != nil {
185 return err
186 }
187
188 _, err = writer.Write(bytes)
189 return err
190
191 case error:
192 _, err := writer.Write([]byte(origin.Error()))
193 return err
194
195 default:
196 v := reflect.Indirect(reflect.ValueOf(data))
197 t := v.Type()
198
199 switch {
200 case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
201 _, err := writer.Write(v.Bytes())
202 return err
203
204 case t.Kind() == reflect.String:
205 _, err := writer.Write([]byte(v.String()))
206 return err
207
208 case t.Kind() == reflect.Struct || t.Kind() == reflect.Slice:
209 b, err := swag.WriteJSON(data)
210 if err != nil {
211 return err
212 }
213
214 _, err = writer.Write(b)
215 return err
216 }
217 }
218
219 return fmt.Errorf("%v (%T) is not supported by the ByteStreamProducer, %s",
220 data, data, "can be resolved by supporting Reader/BinaryMarshaler interface")
221 })
222 }
223
View as plain text