request.go 2.11 KB
Newer Older
Matt Bell's avatar
Matt Bell committed
1 2
package commands

3 4 5 6 7 8
import (
	"fmt"
	"reflect"
	"strconv"
)

Matt Bell's avatar
Matt Bell committed
9 10
// Request represents a call to a command from a consumer
type Request struct {
11
	path			[]string
Matt Bell's avatar
Matt Bell committed
12 13
	options   map[string]interface{}
	arguments []string
Matt Bell's avatar
Matt Bell committed
14 15
}

16 17 18 19
func (r *Request) Path() []string {
	return r.path
}

20 21 22 23
func (r *Request) SetPath(path []string) {
	r.path = path
}

24
func (r *Request) Option(name string) interface{} {
Matt Bell's avatar
Matt Bell committed
25
	return r.options[name]
Matt Bell's avatar
Matt Bell committed
26 27
}

28 29
func (r *Request) SetOption(name string, value interface{}) {
	r.options[name] = value
30 31
}

32
func (r *Request) Arguments() []string {
Matt Bell's avatar
Matt Bell committed
33
	return r.arguments
34
}
Matt Bell's avatar
Matt Bell committed
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
type converter func(string)(interface{}, error)
var converters map[reflect.Kind]converter = map[reflect.Kind]converter{
	Bool: func(v string)(interface{}, error) {
		if v == "" {
			return true, nil
		}
		return strconv.ParseBool(v)
	},
	Int: func(v string)(interface{}, error) {
		return strconv.ParseInt(v, 0, 32)
	},
	Uint: func(v string)(interface{}, error) {
		return strconv.ParseInt(v, 0, 32)
	},
	Float: func(v string)(interface{}, error) {
		return strconv.ParseFloat(v, 64)
	},
}

func (r *Request) convertOptions(options map[string]Option) error {
	converted := make(map[string]interface{})

	for k, v := range r.options {
		opt, ok := options[k]
		if !ok {
			return fmt.Errorf("Unrecognized option: '%s'", k)
		}

		kind := reflect.TypeOf(v).Kind()
		var value interface{}

		if kind != opt.Type {
			if kind == String {
				convert := converters[opt.Type]
				val, err := convert(v.(string))
				if err != nil {
					return fmt.Errorf("Could not convert string value '%s' to type '%s'",
						v, opt.Type.String())
				}
				value = val

			} else {
				return fmt.Errorf("Option '%s' should be type '%s', but got type '%s'",
					k, opt.Type.String(), kind.String())
			}
		} else {
			value = v
		}

		for _, name := range opt.Names {
			if _, ok := r.options[name]; name != k && ok {
				return fmt.Errorf("Duplicate command options were provided ('%s' and '%s')",
					k, name)
			}

		  converted[name] = value
		}
	}

	r.options = converted
	return nil
}

Matt Bell's avatar
Matt Bell committed
99
func NewRequest() *Request {
Matt Bell's avatar
Matt Bell committed
100
	return &Request{
101
		make([]string, 0),
Matt Bell's avatar
Matt Bell committed
102 103 104
		make(map[string]interface{}),
		make([]string, 0),
	}
Matt Bell's avatar
Matt Bell committed
105
}