response.go 1.5 KB
Newer Older
Matt Bell's avatar
Matt Bell committed
1 2
package commands

3
import (
Matt Bell's avatar
Matt Bell committed
4 5 6 7
	"encoding/json"
	"encoding/xml"
	"fmt"
	"strings"
8 9
)

Matt Bell's avatar
Matt Bell committed
10
type ErrorType uint
Matt Bell's avatar
Matt Bell committed
11

Matt Bell's avatar
Matt Bell committed
12
const (
Matt Bell's avatar
Matt Bell committed
13 14 15
	Normal ErrorType = iota // general errors
	Client                  // error was caused by the client, (e.g. invalid CLI usage)
	// TODO: add more types of errors for better error-specific handling
Matt Bell's avatar
Matt Bell committed
16 17
)

18 19
// Error is a struct for marshalling errors
type Error struct {
Matt Bell's avatar
Matt Bell committed
20 21
	Message string
	Code    ErrorType
22 23
}

24
type EncodingType string
Matt Bell's avatar
Matt Bell committed
25

26
const (
Matt Bell's avatar
Matt Bell committed
27 28 29
	Json = "json"
	Xml  = "xml"
	// TODO: support more encoding types
30 31
)

Matt Bell's avatar
Matt Bell committed
32 33
type Marshaller func(v interface{}) ([]byte, error)

34
var marshallers = map[EncodingType]Marshaller{
Matt Bell's avatar
Matt Bell committed
35 36
	Json: json.Marshal,
	Xml:  xml.Marshal,
37 38
}

Matt Bell's avatar
Matt Bell committed
39
type Response struct {
Matt Bell's avatar
Matt Bell committed
40 41 42 43
	req       *Request
	Error     error
	ErrorType ErrorType
	Value     interface{}
Matt Bell's avatar
Matt Bell committed
44 45 46
}

func (r *Response) SetError(err error, errType ErrorType) {
Matt Bell's avatar
Matt Bell committed
47 48
	r.Error = err
	r.ErrorType = errType
Matt Bell's avatar
Matt Bell committed
49 50
}

51
func (r *Response) FormatError() Error {
Matt Bell's avatar
Matt Bell committed
52
	return Error{r.Error.Error(), r.ErrorType}
53 54
}

55
func (r *Response) Marshal() ([]byte, error) {
Matt Bell's avatar
Matt Bell committed
56 57 58
	if r.Error == nil && r.Value == nil {
		return nil, fmt.Errorf("No error or value set, there is nothing to marshal")
	}
59

Matt Bell's avatar
Matt Bell committed
60 61 62 63 64
	enc := r.req.Option("enc")
	if enc == nil {
		return nil, fmt.Errorf("No encoding type was specified")
	}
	encType := EncodingType(strings.ToLower(enc.(string)))
Matt Bell's avatar
Matt Bell committed
65

Matt Bell's avatar
Matt Bell committed
66 67 68 69
	marshaller, ok := marshallers[encType]
	if !ok {
		return nil, fmt.Errorf("No marshaller found for encoding type '%s'", enc)
	}
70

Matt Bell's avatar
Matt Bell committed
71 72 73 74 75 76
	if r.Error != nil {
		err := r.FormatError()
		return marshaller(err)
	} else {
		return marshaller(r.Value)
	}
77
}