Esempio n. 1
0
func (d *decoder) decodeSlice(name string, o *hcl.Object, result reflect.Value) error {
	// If we have an interface, then we can address the interface,
	// but not the slice itself, so get the element but set the interface
	set := result
	if result.Kind() == reflect.Interface {
		result = result.Elem()
	}

	// Create the slice if it isn't nil
	resultType := result.Type()
	resultElemType := resultType.Elem()
	if result.IsNil() {
		resultSliceType := reflect.SliceOf(resultElemType)
		result = reflect.MakeSlice(
			resultSliceType, 0, 0)
	}

	// Determine how we're doing this
	expand := true
	switch o.Type {
	case hcl.ValueTypeObject:
		expand = false
	default:
		// Array or anything else: we expand values and take it all
	}

	i := 0
	for _, o := range o.Elem(expand) {
		fieldName := fmt.Sprintf("%s[%d]", name, i)

		// Decode
		val := reflect.Indirect(reflect.New(resultElemType))
		if err := d.decode(fieldName, o, val); err != nil {
			return err
		}

		// Append it onto the slice
		result = reflect.Append(result, val)

		i += 1
	}

	set.Set(result)
	return nil
}
Esempio n. 2
0
func (d *decoder) decodeMap(name string, o *hcl.Object, result reflect.Value) error {
	if o.Type != hcl.ValueTypeObject {
		return fmt.Errorf("%s: not an object type for map (%v)", name, o.Type)
	}

	// If we have an interface, then we can address the interface,
	// but not the slice itself, so get the element but set the interface
	set := result
	if result.Kind() == reflect.Interface {
		result = result.Elem()
	}

	resultType := result.Type()
	resultElemType := resultType.Elem()
	resultKeyType := resultType.Key()
	if resultKeyType.Kind() != reflect.String {
		return fmt.Errorf(
			"%s: map must have string keys", name)
	}

	// Make a map if it is nil
	resultMap := result
	if result.IsNil() {
		resultMap = reflect.MakeMap(
			reflect.MapOf(resultKeyType, resultElemType))
	}

	// Go through each element and decode it.
	for _, o := range o.Elem(false) {
		if o.Value == nil {
			continue
		}

		for _, o := range o.Elem(true) {
			// Make the field name
			fieldName := fmt.Sprintf("%s.%s", name, o.Key)

			// Get the key/value as reflection values
			key := reflect.ValueOf(o.Key)
			val := reflect.Indirect(reflect.New(resultElemType))

			// If we have a pre-existing value in the map, use that
			oldVal := resultMap.MapIndex(key)
			if oldVal.IsValid() {
				val.Set(oldVal)
			}

			// Decode!
			if err := d.decode(fieldName, o, val); err != nil {
				return err
			}

			// Set the value on the map
			resultMap.SetMapIndex(key, val)
		}
	}

	// Set the final map if we can
	set.Set(resultMap)
	return nil
}