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  }