github.com/bhameyie/otto@v0.2.1-0.20160406174117-16052efa52ec/helper/schema/field_data.go (about) 1 package schema 2 3 import ( 4 "fmt" 5 6 "github.com/mitchellh/mapstructure" 7 ) 8 9 // FieldData is a structure that given a schema and a raw map[string]interface{} 10 // provides helper functions for validating and retrieving typed values from 11 // the data. 12 type FieldData struct { 13 Raw map[string]interface{} 14 Schema map[string]*FieldSchema 15 } 16 17 // Cycle through raw data and validate conversions in 18 // the schema, so we don't get an error/panic later when 19 // trying to get data out. Data not in the schema is not 20 // an error at this point, so we don't worry about it. 21 func (d *FieldData) Validate() error { 22 for field, value := range d.Raw { 23 schema, ok := d.Schema[field] 24 if !ok { 25 continue 26 } 27 28 switch schema.Type { 29 case TypeBool, TypeInt, TypeMap, TypeString: 30 _, _, err := d.getPrimitive(field, schema) 31 if err != nil { 32 return fmt.Errorf("Error converting input %v for field %s", value, field) 33 } 34 default: 35 return fmt.Errorf("unknown field type %s for field %s", 36 schema.Type, field) 37 } 38 } 39 40 return nil 41 } 42 43 // Get gets the value for the given field. If the key is an invalid field, 44 // FieldData will panic. If you want a safer version of this method, use 45 // GetOk. If the field k is not set, the default value (if set) will be 46 // returned, otherwise the zero value will be returned. 47 func (d *FieldData) Get(k string) interface{} { 48 schema, ok := d.Schema[k] 49 if !ok { 50 panic(fmt.Sprintf("field %s not in the schema", k)) 51 } 52 53 value, ok := d.GetOk(k) 54 if !ok { 55 value = schema.DefaultOrZero() 56 } 57 58 return value 59 } 60 61 // GetOk gets the value for the given field. The second return value 62 // will be false if the key is invalid or the key is not set at all. 63 func (d *FieldData) GetOk(k string) (interface{}, bool) { 64 schema, ok := d.Schema[k] 65 if !ok { 66 return nil, false 67 } 68 69 result, ok, err := d.GetOkErr(k) 70 if err != nil { 71 panic(fmt.Sprintf("error reading %s: %s", k, err)) 72 } 73 74 if ok && result == nil { 75 result = schema.DefaultOrZero() 76 } 77 78 return result, ok 79 } 80 81 // GetOkErr is the most conservative of all the Get methods. It returns 82 // whether key is set or not, but also an error value. The error value is 83 // non-nil if the field doesn't exist or there was an error parsing the 84 // field value. 85 func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) { 86 schema, ok := d.Schema[k] 87 if !ok { 88 return nil, false, fmt.Errorf("unknown field: %s", k) 89 } 90 91 switch schema.Type { 92 case TypeBool, TypeInt, TypeMap, TypeString: 93 return d.getPrimitive(k, schema) 94 default: 95 return nil, false, 96 fmt.Errorf("unknown field type %s for field %s", schema.Type, k) 97 } 98 } 99 100 func (d *FieldData) getPrimitive( 101 k string, schema *FieldSchema) (interface{}, bool, error) { 102 raw, ok := d.Raw[k] 103 if !ok { 104 return nil, false, nil 105 } 106 107 switch schema.Type { 108 case TypeBool: 109 var result bool 110 if err := mapstructure.WeakDecode(raw, &result); err != nil { 111 return nil, true, err 112 } 113 114 return result, true, nil 115 case TypeInt: 116 var result int 117 if err := mapstructure.WeakDecode(raw, &result); err != nil { 118 return nil, true, err 119 } 120 121 return result, true, nil 122 case TypeString: 123 var result string 124 if err := mapstructure.WeakDecode(raw, &result); err != nil { 125 return nil, true, err 126 } 127 128 return result, true, nil 129 case TypeMap: 130 var result map[string]interface{} 131 if err := mapstructure.WeakDecode(raw, &result); err != nil { 132 return nil, true, err 133 } 134 135 return result, true, nil 136 137 default: 138 panic(fmt.Sprintf("Unknown type: %s", schema.Type)) 139 } 140 }