Ejemplo n.º 1
3
// deserializeStructInternal is a helper function for deserializeStruct.
// It takes a gob decoder and struct field metadata, and then assigns the correct value to the specified struct field.
func deserializeStructInternal(dec *gob.Decoder, fi *fieldInfo, fieldName string, nameParts []string, slice, zeroValue bool, structHistory map[string]map[string]bool, v reflect.Value, t reflect.Type) error {
	if len(fi.sliceIndex) > 0 {
		v = v.FieldByIndex(fi.sliceIndex)
		t = v.Type()

		var sv reflect.Value
		createNew := false
		nameIdx := len(fi.sliceIndex)
		absName, childName := strings.Join(nameParts[:nameIdx], "."), strings.Join(nameParts[nameIdx:], ".")
		sh, ok := structHistory[absName]
		if !ok || sh[childName] {
			sh = make(map[string]bool, 8)
			structHistory[absName] = sh
			createNew = true
		} else if len(sh) == 0 {
			createNew = true
		}

		if createNew {
			structType := t.Elem()
			sv = reflect.New(structType).Elem()
			v.Set(reflect.Append(v, sv))
		}

		sv = v.Index(v.Len() - 1)
		sh[childName] = true

		v = sv
		t = v.Type()
	}

	vf := v.FieldByIndex(fi.fieldIndex)

	if vf.Kind() == reflect.Slice && !slice {
		elemType := vf.Type().Elem()
		if elemType.Kind() == reflect.Uint8 {
			if !zeroValue {
				if err := dec.DecodeValue(vf); err != nil {
					return fmt.Errorf("goon: Failed to decode field %v - %v", fieldName, err)
				}
			}
		} else {
			ev := reflect.New(elemType).Elem()
			if !zeroValue {
				if err := dec.DecodeValue(ev); err != nil {
					return fmt.Errorf("goon: Failed to decode field %v - %v", fieldName, err)
				}
			}
			vf.Set(reflect.Append(vf, ev))
		}
	} else if !zeroValue {
		if err := dec.DecodeValue(vf); err != nil {
			return fmt.Errorf("goon: Failed to decode field %v - %v", fieldName, err)
		}
	}

	return nil
}