// 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 }