forked from ipfs/go-ipfs-cmds
-
Notifications
You must be signed in to change notification settings - Fork 0
/
responseemitter.go
80 lines (64 loc) · 1.78 KB
/
responseemitter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package cmds
import (
"fmt"
"io"
"github.com/ipfs/go-ipfs-cmdkit"
)
// Single can be used to signal to any ResponseEmitter that only one value will be emitted.
// This is important e.g. for the http.ResponseEmitter so it can set the HTTP headers appropriately.
type Single struct {
Value interface{}
}
func (s Single) String() string {
return fmt.Sprintf("Single{%v}", s.Value)
}
func (s Single) GoString() string {
return fmt.Sprintf("Single{%#v}", s.Value)
}
// EmitOnce is a helper that emits a value wrapped in Single, to signal that this will be the only value sent.
func EmitOnce(re ResponseEmitter, v interface{}) error {
return re.Emit(Single{v})
}
// ResponseEmitter encodes and sends the command code's output to the client.
// It is all a command can write to.
type ResponseEmitter interface {
// closes http conn or channel
io.Closer
// SetLength sets the length of the output
// err is an interface{} so we don't have to manually convert to error.
SetLength(length uint64)
// SetError sets the response error
// err is an interface{} so we don't have to manually convert to error.
SetError(err interface{}, code cmdkit.ErrorType)
// Emit sends a value
// if value is io.Reader we just copy that to the connection
// other values are marshalled
Emit(value interface{}) error
}
type EncodingEmitter interface {
ResponseEmitter
SetEncoder(func(io.Writer) Encoder)
}
type Header interface {
Head() Head
}
// Copy sends all values received on res to re. If res is closed, it closes re.
func Copy(re ResponseEmitter, res Response) error {
re.SetLength(res.Length())
for {
v, err := res.RawNext()
switch err {
case nil:
// all good, go on
case io.EOF:
re.Close()
return nil
default:
return err
}
err = re.Emit(v)
if err != nil {
return err
}
}
}