github.com/viant/toolbox@v0.34.5/converter.go (about) 1 package toolbox 2 3 import ( 4 "errors" 5 "fmt" 6 "math" 7 "reflect" 8 "strconv" 9 "strings" 10 "time" 11 ) 12 13 //DefaultDateLayout is set to 2006-01-02 15:04:05.000 14 var DefaultDateLayout = "2006-01-02 15:04:05.000" 15 var numericTypes = []reflect.Type{ 16 reflect.TypeOf(int(0)), 17 reflect.TypeOf(int8(0)), 18 reflect.TypeOf(int16(0)), 19 reflect.TypeOf(int32(0)), 20 reflect.TypeOf(int64(0)), 21 22 reflect.TypeOf(uint(0)), 23 reflect.TypeOf(uint8(0)), 24 reflect.TypeOf(uint16(0)), 25 reflect.TypeOf(uint32(0)), 26 reflect.TypeOf(uint64(0)), 27 28 reflect.TypeOf(float32(0.0)), 29 reflect.TypeOf(float64(0.0)), 30 } 31 32 //AsString converts an input to string. 33 func AsString(input interface{}) string { 34 switch value := input.(type) { 35 case string: 36 return value 37 case *string: 38 if value == nil { 39 return "" 40 } 41 return *value 42 case []byte: 43 return string(value) 44 case []interface{}: 45 if len(value) == 0 { 46 return "" 47 } 48 if _, isByte := value[0].(byte); isByte { 49 var stringBytes = make([]byte, len(value)) 50 for i, v := range value { 51 stringBytes[i] = v.(byte) 52 } 53 return string(stringBytes) 54 } 55 var result = "" 56 for _, v := range value { 57 result += AsString(v) 58 } 59 return result 60 } 61 reflectValue := reflect.ValueOf(input) 62 if reflectValue.Kind() == reflect.Ptr { 63 reflectValue = reflectValue.Elem() 64 } 65 switch reflectValue.Kind() { 66 case reflect.Bool: 67 return strconv.FormatBool(reflectValue.Bool()) 68 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 69 return strconv.FormatInt(reflectValue.Int(), 10) 70 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 71 return strconv.FormatUint(reflectValue.Uint(), 10) 72 case reflect.Float64: 73 return strconv.FormatFloat(reflectValue.Float(), 'g', -1, 64) 74 case reflect.Float32: 75 return strconv.FormatFloat(reflectValue.Float(), 'g', -1, 32) 76 } 77 return fmt.Sprintf("%v", input) 78 } 79 80 //CanConvertToFloat checkis if float conversion is possible. 81 func CanConvertToFloat(value interface{}) bool { 82 if _, ok := value.(float64); ok { 83 return true 84 } 85 _, err := strconv.ParseFloat(AsString(value), 64) 86 return err == nil 87 } 88 89 //AsFloat converts an input to float. 90 func AsFloat(value interface{}) float64 { 91 if result, err := ToFloat(value); err == nil { 92 return result 93 } 94 return 0 95 } 96 97 //ToFloat converts an input to float or error 98 func ToFloat(value interface{}) (float64, error) { 99 if value == nil { 100 return 0, NewNilPointerError("float value was nil") 101 } 102 switch actualValue := value.(type) { 103 case float64: 104 return actualValue, nil 105 case int: 106 return float64(actualValue), nil 107 case uint: 108 return float64(actualValue), nil 109 case int64: 110 return float64(actualValue), nil 111 case uint64: 112 return float64(actualValue), nil 113 case int32: 114 return float64(actualValue), nil 115 case uint32: 116 return float64(actualValue), nil 117 case float32: 118 return float64(actualValue), nil 119 case bool: 120 if actualValue { 121 return 1.0, nil 122 } 123 return 0.0, nil 124 } 125 if reflect.TypeOf(value).Kind() == reflect.Ptr { 126 floatValue, err := ToFloat(DereferenceValue(value)) 127 if err != nil && IsNilPointerError(err) { 128 return floatValue, nil 129 } 130 return floatValue, err 131 } 132 valueAsString := AsString(DereferenceValue(value)) 133 return strconv.ParseFloat(valueAsString, 64) 134 } 135 136 //ToBoolean converts an input to bool. 137 func ToBoolean(value interface{}) (bool, error) { 138 if boolValue, ok := value.(bool); ok { 139 return boolValue, nil 140 } 141 valueAsString := AsString(value) 142 return strconv.ParseBool(valueAsString) 143 } 144 145 //AsBoolean converts an input to bool. 146 func AsBoolean(value interface{}) bool { 147 result, err := ToBoolean(value) 148 if err != nil { 149 return false 150 } 151 return result 152 } 153 154 //CanConvertToInt returns true if an input can be converted to int value. 155 func CanConvertToInt(value interface{}) bool { 156 if _, ok := value.(int); ok { 157 return true 158 } 159 valueAsString := AsString(value) 160 if _, err := strconv.ParseInt(valueAsString, 10, 64); err == nil { 161 return true 162 } 163 return false 164 } 165 166 var intBitSize = reflect.TypeOf(int64(0)).Bits() 167 168 //AsInt converts an input to int. 169 func AsInt(value interface{}) int { 170 var result, err = ToInt(value) 171 if err == nil { 172 return result 173 } 174 return 0 175 } 176 177 //ToInt converts input value to int or error 178 func ToInt(value interface{}) (int, error) { 179 if text, ok := value.(string);ok { //common use case 180 return strconv.Atoi(text) 181 } 182 return toInt(value) 183 } 184 185 func toInt(value interface{}) (int, error) { 186 if value == nil { 187 return 0, NewNilPointerError("int value was nil") 188 } 189 switch actual := value.(type) { 190 case int: 191 return actual, nil 192 case *int: 193 if actual == nil { 194 return 0, nil 195 } 196 return *actual, nil 197 case int8: 198 return int(actual), nil 199 case int16: 200 return int(actual), nil 201 case int32: 202 return int(actual), nil 203 case *int64: 204 if actual == nil { 205 return 0, nil 206 } 207 return int(*actual), nil 208 case int64: 209 return int(actual), nil 210 case uint: 211 return int(actual), nil 212 case uint8: 213 return int(actual), nil 214 case uint16: 215 return int(actual), nil 216 case uint32: 217 return int(actual), nil 218 case uint64: 219 return int(actual), nil 220 case float32: 221 return int(actual), nil 222 case float64: 223 return int(actual), nil 224 case bool: 225 if actual { 226 return 1, nil 227 } 228 return 0, nil 229 } 230 if reflect.TypeOf(value).Kind() == reflect.Ptr { 231 value := DereferenceValue(value) 232 if intValue, err := ToInt(value); err != nil { 233 if err != nil && IsNilPointerError(err) { 234 return intValue, err 235 } 236 return intValue, err 237 } 238 } 239 valueAsString := AsString(value) 240 if strings.Contains(valueAsString, ".") { 241 floatValue, err := strconv.ParseFloat(valueAsString, intBitSize) 242 if err != nil { 243 return 0, err 244 } 245 return int(floatValue), nil 246 } 247 result, err := strconv.ParseInt(valueAsString, 10, 64) 248 return int(result), err 249 } 250 251 func unitToTime(timestamp int64) *time.Time { 252 var timeValue time.Time 253 if timestamp > math.MaxUint32 { 254 var timestampInMs = timestamp / 1000000 255 if timestampInMs > math.MaxUint32 { 256 timeValue = time.Unix(0, timestamp) 257 } else { 258 timeValue = time.Unix(0, timestamp*1000000) 259 } 260 } else { 261 timeValue = time.Unix(timestamp, 0) 262 } 263 return &timeValue 264 } 265 266 func textToTime(value, dateLayout string) (*time.Time, error) { 267 floatValue, err := ToFloat(value) 268 if err == nil { 269 return unitToTime(int64(floatValue)), nil 270 } 271 timeValue, err := ParseTime(value, dateLayout) 272 if err != nil { 273 if dateLayout != "" { 274 if len(value) > len(dateLayout) { 275 value = string(value[:len(dateLayout)]) 276 } 277 timeValue, err = ParseTime(value, dateLayout) 278 } 279 if err != nil { //JSON default time format fallback 280 if timeValue, err = ParseTime(value, time.RFC3339); err == nil { 281 return &timeValue, err 282 } 283 return nil, err 284 } 285 } 286 return &timeValue, nil 287 } 288 289 //ToTime converts value to time, optionally uses layout if value if of string type 290 func ToTime(value interface{}, dateLayout string) (*time.Time, error) { 291 if value == nil { 292 return nil, errors.New("values was empty") 293 } 294 switch actual := value.(type) { 295 case time.Time: 296 return &actual, nil 297 case *time.Time: 298 return actual, nil 299 case float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: 300 var floatValue, _ = ToFloat(value) 301 return unitToTime(int64(floatValue)), nil 302 case *float32, *float64, *int, *int8, *int16, *int32, *int64, *uint, *uint8, *uint16, *uint32, *uint64: 303 actual = DereferenceValue(actual) 304 return ToTime(actual, dateLayout) 305 case string: 306 return textToTime(actual, dateLayout) 307 case map[string]interface{}: 308 if len(actual) == 0 { 309 return nil, nil 310 } 311 } 312 textValue := AsString(DereferenceValue(value)) 313 return textToTime(textValue, dateLayout) 314 } 315 316 //AsTime converts an input to time, it takes time input, dateLaout as parameters. 317 func AsTime(value interface{}, dateLayout string) *time.Time { 318 result, err := ToTime(value, dateLayout) 319 if err != nil { 320 return nil 321 } 322 return result 323 } 324 325 //DiscoverValueAndKind discovers input kind, it applies checks of the following types: int, float, bool, string 326 func DiscoverValueAndKind(input string) (interface{}, reflect.Kind) { 327 if len(input) == 0 { 328 return nil, reflect.Invalid 329 } 330 if strings.Contains(input, ".") { 331 if floatValue, err := strconv.ParseFloat(input, 64); err == nil { 332 return floatValue, reflect.Float64 333 } 334 } 335 if intValue, err := strconv.ParseInt(input, 10, 64); err == nil { 336 return int(intValue), reflect.Int 337 } else if strings.ToLower(input) == "true" { 338 return true, reflect.Bool 339 } else if strings.ToLower(input) == "false" { 340 return false, reflect.Bool 341 } 342 return input, reflect.String 343 } 344 345 //DiscoverCollectionValuesAndKind discovers passed in slice item kind, and returns slice of values converted to discovered type. 346 //It tries the following kind int, float, bool, string 347 func DiscoverCollectionValuesAndKind(values interface{}) ([]interface{}, reflect.Kind) { 348 var candidateKind = reflect.Int 349 var result = make([]interface{}, 0) 350 ProcessSlice(values, func(value interface{}) bool { 351 stringValue := strings.ToLower(AsString(value)) 352 switch candidateKind { 353 case reflect.String: 354 return false 355 case reflect.Int: 356 if !strings.Contains(stringValue, ".") && CanConvertToInt(value) { 357 return true 358 } 359 candidateKind = reflect.Float64 360 fallthrough 361 case reflect.Float64: 362 if CanConvertToFloat(value) { 363 return true 364 } 365 candidateKind = reflect.Bool 366 fallthrough 367 368 case reflect.Bool: 369 if stringValue == "true" || stringValue == "false" { 370 return true 371 } 372 candidateKind = reflect.String 373 } 374 return true 375 }) 376 ProcessSlice(values, func(value interface{}) bool { 377 switch candidateKind { 378 case reflect.Float64: 379 result = append(result, AsFloat(value)) 380 case reflect.Int: 381 result = append(result, AsInt(value)) 382 case reflect.Bool: 383 result = append(result, AsBoolean(value)) 384 default: 385 result = append(result, AsString(value)) 386 } 387 return true 388 }) 389 return result, candidateKind 390 } 391 392 //UnwrapValue returns value 393 func UnwrapValue(value *reflect.Value) interface{} { 394 return value.Interface() 395 } 396 397 //NewBytes copies from input 398 func NewBytes(input []byte) []byte { 399 if input != nil { 400 var result = make([]byte, len(input)) 401 copy(result, input) 402 return result 403 } 404 return nil 405 } 406 407 //ParseTime parses time, adjusting date layout to length of input 408 func ParseTime(input, layout string) (time.Time, error) { 409 if len(layout) == 0 { 410 layout = DefaultDateLayout 411 } //GetFieldValue returns field value 412 lastPosition := len(input) 413 if lastPosition >= len(layout) { 414 lastPosition = len(layout) 415 } 416 layout = layout[0:lastPosition] 417 418 return time.Parse(layout, input) 419 } 420 421 //Converter represets data converter, it converts incompatibe data structure, like map and struct, string and time, *string to string, etc. 422 type Converter struct { 423 DateLayout string 424 MappedKeyTag string 425 } 426 427 func (c *Converter) assignConvertedMap(target, source interface{}, targetIndirectValue reflect.Value, targetIndirectPointerType reflect.Type) error { 428 mapType := DiscoverTypeByKind(target, reflect.Map) 429 mapPointer := reflect.New(mapType) 430 mapValueType := mapType.Elem() 431 mapKeyType := mapType.Key() 432 newMap := mapPointer.Elem() 433 newMap.Set(reflect.MakeMap(mapType)) 434 var err error 435 err = ProcessMap(source, func(key, value interface{}) bool { 436 if value == nil { 437 return true 438 } 439 mapValueType = reflect.TypeOf(value) 440 targetMapValuePointer := reflect.New(mapValueType) 441 err = c.AssignConverted(targetMapValuePointer.Interface(), value) 442 if err != nil { 443 err = fmt.Errorf("failed to assigned converted map value %v to %v due to %v", source, target, err) 444 return false 445 } 446 447 targetMapKeyPointer := reflect.New(mapKeyType) 448 err = c.AssignConverted(targetMapKeyPointer.Interface(), key) 449 if err != nil { 450 err = fmt.Errorf("failed to assigned converted map key %v to %v due to %v", source, target, err) 451 return false 452 } 453 var elementKey = targetMapKeyPointer.Elem() 454 var elementValue = targetMapValuePointer.Elem() 455 456 if elementKey.Type() != mapKeyType { 457 if elementKey.Type().AssignableTo(mapKeyType) { 458 elementKey = elementKey.Convert(mapKeyType) 459 } 460 } 461 if !elementValue.Type().AssignableTo(newMap.Type().Elem()) { 462 var compatibleValue = reflect.New(newMap.Type().Elem()) 463 err = c.AssignConverted(compatibleValue.Interface(), elementValue.Interface()) 464 if err != nil { 465 return false 466 } 467 elementValue = compatibleValue.Elem() 468 } 469 newMap.SetMapIndex(elementKey, elementValue) 470 return true 471 }) 472 if err != nil { 473 return err 474 } 475 if targetIndirectPointerType.Kind() == reflect.Map { 476 if targetIndirectValue.Type().AssignableTo(mapPointer.Type()) { 477 targetIndirectValue.Set(mapPointer) 478 } else { 479 targetIndirectValue.Set(mapPointer.Elem()) 480 } 481 } else { 482 targetIndirectValue.Set(newMap) 483 } 484 return err 485 486 } 487 488 func (c *Converter) assignConvertedSlice(target, source interface{}, targetIndirectValue reflect.Value, targetIndirectPointerType reflect.Type) error { 489 sliceType := DiscoverTypeByKind(target, reflect.Slice) 490 slicePointer := reflect.New(sliceType) 491 slice := slicePointer.Elem() 492 componentType := DiscoverComponentType(target) 493 var err error 494 ProcessSlice(source, func(item interface{}) bool { 495 var targetComponentPointer = reflect.New(componentType) 496 if componentType.Kind() == reflect.Map { 497 targetComponent := reflect.MakeMap(componentType) 498 targetComponentPointer.Elem().Set(targetComponent) 499 } 500 err = c.AssignConverted(targetComponentPointer.Interface(), item) 501 if err != nil { 502 err = fmt.Errorf("failed to convert slice item from %T to %T, values: from %v to %v, due to %v", item, targetComponentPointer.Interface(), item, targetComponentPointer.Interface(), err) 503 return false 504 } 505 slice.Set(reflect.Append(slice, targetComponentPointer.Elem())) 506 return true 507 }) 508 509 if targetIndirectPointerType.Kind() == reflect.Slice { 510 targetIndirectValue.Set(slicePointer) 511 } else { 512 targetIndirectValue.Set(slice) 513 } 514 return err 515 } 516 517 func (c *Converter) assignConvertedStruct(target interface{}, inputMap map[string]interface{}, targetIndirectValue reflect.Value, targetIndirectPointerType reflect.Type) error { 518 newStructPointer := reflect.New(targetIndirectValue.Type()) 519 newStruct := newStructPointer.Elem() 520 fieldsMapping := NewFieldSettingByKey(newStructPointer.Interface(), c.MappedKeyTag) 521 522 var defaultValueMap = make(map[string]interface{}) 523 524 var anonymousValueMap map[string]reflect.Value 525 var anonymousFields map[string]reflect.Value 526 527 for _, value := range fieldsMapping { 528 if defaultValue, ok := value[defaultKey]; ok { 529 var fieldName = value[fieldNameKey] 530 defaultValueMap[fieldName] = defaultValue 531 } 532 if index, ok := value[fieldIndexKey]; ok { 533 if len(anonymousValueMap) == 0 { 534 anonymousValueMap = make(map[string]reflect.Value) 535 anonymousFields = make(map[string]reflect.Value) 536 } 537 field := newStruct.Field(AsInt(index)) 538 if field.Type().Kind() == reflect.Ptr { 539 fieldStruct := reflect.New(field.Type().Elem()) 540 anonymousValueMap[index] = fieldStruct 541 anonymousFields[index] = field 542 } else { 543 anonymousValueMap[index] = field.Addr() 544 anonymousFields[index] = field.Addr() 545 } 546 } 547 } 548 549 for key, value := range inputMap { 550 aStruct := newStruct 551 mapping, found := fieldsMapping[strings.ToLower(key)] 552 if found { 553 var field reflect.Value 554 fieldName := mapping[fieldNameKey] 555 if fieldIndex, ok := mapping[fieldIndexKey]; ok { 556 var structPointer = anonymousValueMap[fieldIndex] 557 if anonymousFields[fieldIndex].CanAddr() { 558 anonymousFields[fieldIndex].Set(structPointer) 559 } 560 aStruct = structPointer.Elem() 561 initAnonymousStruct(structPointer.Interface()) 562 } 563 field = aStruct.FieldByName(fieldName) 564 fieldType, _ := aStruct.Type().FieldByName(fieldName) 565 if isExported := fieldType.PkgPath == ""; !isExported { 566 structField := &StructField{ 567 Owner: newStructPointer, 568 Value: field, 569 Type: fieldType, 570 } 571 if !onUnexportedHandler(structField) { 572 continue 573 } 574 field = structField.Value 575 } 576 if _, has := defaultValueMap[fieldName]; has { 577 delete(defaultValueMap, fieldName) 578 } 579 previousLayout := c.DateLayout 580 if HasTimeLayout(mapping) { 581 c.DateLayout = GetTimeLayout(mapping) 582 c.DateLayout = previousLayout 583 } 584 585 if (!field.CanAddr()) && field.Kind() == reflect.Ptr { 586 if err := c.AssignConverted(field.Interface(), value); err != nil { 587 return fmt.Errorf("failed to convert %v to %v due to %v", value, field, err) 588 } 589 590 } else { 591 if value == nil { 592 continue 593 } 594 if err := c.AssignConverted(field.Addr().Interface(), value); err != nil { 595 return fmt.Errorf("failed to convert %v to %v due to %v", value, field, err) 596 } 597 } 598 if HasTimeLayout(mapping) { 599 c.DateLayout = previousLayout 600 } 601 } 602 } 603 604 for fieldName, value := range defaultValueMap { 605 field := newStruct.FieldByName(fieldName) 606 err := c.AssignConverted(field.Addr().Interface(), value) 607 if err != nil { 608 return fmt.Errorf("failed to assign default value %v to %v due to %v", value, field, err) 609 } 610 } 611 612 if targetIndirectPointerType.Kind() == reflect.Slice { 613 targetIndirectValue.Set(newStructPointer) 614 } else { 615 targetIndirectValue.Set(newStruct) 616 } 617 return nil 618 } 619 620 //customConverter map of target, source type with converter 621 var customConverter = make(map[reflect.Type]map[reflect.Type]func(target, source interface{}) error) 622 623 //RegisterConverter register custom converter for supplied target, source type 624 func RegisterConverter(target, source reflect.Type, converter func(target, source interface{}) error) { 625 if _, ok := customConverter[target]; !ok { 626 customConverter[target] = make(map[reflect.Type]func(target, source interface{}) error) 627 } 628 customConverter[target][source] = converter 629 } 630 631 //GetConverter returns register converter for supplied target and source type 632 func GetConverter(target, source interface{}) (func(target, source interface{}) error, bool) { 633 sourceConverters, ok := customConverter[reflect.TypeOf(target)] 634 if !ok { 635 return nil, false 636 } 637 converter, ok := sourceConverters[reflect.TypeOf(source)] 638 return converter, ok 639 } 640 641 //AssignConverted assign to the target source, target needs to be pointer, input has to be convertible or compatible type 642 func (c *Converter) AssignConverted(target, source interface{}) error { 643 if target == nil { 644 return fmt.Errorf("destination Pointer was nil %v %v", target, source) 645 } 646 if source == nil { 647 return nil 648 } 649 switch targetValuePointer := target.(type) { 650 case *string: 651 switch sourceValue := source.(type) { 652 case string: 653 *targetValuePointer = sourceValue 654 return nil 655 case *string: 656 *targetValuePointer = *sourceValue 657 return nil 658 case []byte: 659 *targetValuePointer = string(sourceValue) 660 return nil 661 case *[]byte: 662 *targetValuePointer = string(NewBytes(*sourceValue)) 663 return nil 664 default: 665 *targetValuePointer = AsString(source) 666 return nil 667 } 668 669 case **string: 670 switch sourceValue := source.(type) { 671 case string: 672 *targetValuePointer = &sourceValue 673 return nil 674 case *string: 675 *targetValuePointer = sourceValue 676 return nil 677 case []byte: 678 var stringSourceValue = string(sourceValue) 679 *targetValuePointer = &stringSourceValue 680 return nil 681 case *[]byte: 682 var stringSourceValue = string(NewBytes(*sourceValue)) 683 *targetValuePointer = &stringSourceValue 684 return nil 685 default: 686 stringSourceValue := AsString(source) 687 *targetValuePointer = &stringSourceValue 688 return nil 689 } 690 691 case *[]string: 692 switch sourceValue := source.(type) { 693 case []string: 694 *targetValuePointer = sourceValue 695 return nil 696 case *[]string: 697 *targetValuePointer = *sourceValue 698 return nil 699 case *string: 700 transient := []string{*sourceValue} 701 *targetValuePointer = transient 702 return nil 703 case string: 704 transient := []string{sourceValue} 705 *targetValuePointer = transient 706 return nil 707 default: 708 if IsSlice(source) { 709 var stingItems = make([]string, 0) 710 ProcessSlice(source, func(item interface{}) bool { 711 stingItems = append(stingItems, AsString(item)) 712 return true 713 }) 714 *targetValuePointer = stingItems 715 return nil 716 } else if IsMap(source) { 717 if len(AsMap(source)) == 0 { 718 return nil 719 } 720 } 721 return fmt.Errorf("expected []string but had: %T", source) 722 } 723 724 case *bool: 725 switch sourceValue := source.(type) { 726 case bool: 727 *targetValuePointer = sourceValue 728 return nil 729 case *bool: 730 *targetValuePointer = *sourceValue 731 return nil 732 733 case int: 734 *targetValuePointer = sourceValue != 0 735 return nil 736 case string: 737 boolValue, err := strconv.ParseBool(sourceValue) 738 if err != nil { 739 return err 740 } 741 742 *targetValuePointer = boolValue 743 return nil 744 case *string: 745 boolValue, err := strconv.ParseBool(*sourceValue) 746 if err != nil { 747 return err 748 } 749 *targetValuePointer = boolValue 750 return nil 751 } 752 753 case **bool: 754 switch sourceValue := source.(type) { 755 case bool: 756 *targetValuePointer = &sourceValue 757 return nil 758 case *bool: 759 *targetValuePointer = sourceValue 760 return nil 761 case int: 762 boolValue := sourceValue != 0 763 *targetValuePointer = &boolValue 764 return nil 765 case string: 766 boolValue, err := strconv.ParseBool(sourceValue) 767 if err != nil { 768 return err 769 } 770 771 *targetValuePointer = &boolValue 772 return nil 773 case *string: 774 boolValue, err := strconv.ParseBool(*sourceValue) 775 if err != nil { 776 return err 777 } 778 *targetValuePointer = &boolValue 779 return nil 780 } 781 case *[]byte: 782 switch sourceValue := source.(type) { 783 case []byte: 784 *targetValuePointer = sourceValue 785 return nil 786 case *[]byte: 787 *targetValuePointer = *sourceValue 788 return nil 789 case string: 790 *targetValuePointer = []byte(sourceValue) 791 return nil 792 case *string: 793 var stringValue = *sourceValue 794 *targetValuePointer = []byte(stringValue) 795 return nil 796 } 797 798 case **[]byte: 799 switch sourceValue := source.(type) { 800 case []byte: 801 bytes := NewBytes(sourceValue) 802 *targetValuePointer = &bytes 803 return nil 804 case *[]byte: 805 bytes := NewBytes(*sourceValue) 806 *targetValuePointer = &bytes 807 return nil 808 case string: 809 bytes := []byte(sourceValue) 810 *targetValuePointer = &bytes 811 return nil 812 case *string: 813 bytes := []byte(*sourceValue) 814 *targetValuePointer = &bytes 815 return nil 816 } 817 818 case *int, *int8, *int16, *int32, *int64: 819 directValue := reflect.Indirect(reflect.ValueOf(targetValuePointer)) 820 var intValue, err = ToInt(source) 821 if err != nil { 822 return err 823 } 824 directValue.SetInt(int64(intValue)) 825 return nil 826 827 case **int, **int8, **int16, **int32, **int64: 828 directType := reflect.TypeOf(targetValuePointer).Elem().Elem() 829 var intValue, err = ToInt(source) 830 831 if err != nil { 832 if IsNilPointerError(err) { 833 return nil 834 } 835 return err 836 } 837 switch directType.Kind() { 838 case reflect.Int8: 839 alignValue := int8(intValue) 840 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 841 case reflect.Int16: 842 alignValue := int16(intValue) 843 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 844 case reflect.Int32: 845 alignValue := int32(intValue) 846 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 847 case reflect.Int64: 848 alignValue := int64(intValue) 849 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 850 default: 851 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&intValue)) 852 } 853 return nil 854 case *uint, *uint8, *uint16, *uint32, *uint64: 855 directValue := reflect.Indirect(reflect.ValueOf(targetValuePointer)) 856 value, err := ToInt(source) 857 if err != nil { 858 return err 859 } 860 directValue.SetUint(uint64(value)) 861 return nil 862 case **uint, **uint8, **uint16, **uint32, **uint64: 863 directType := reflect.TypeOf(targetValuePointer).Elem().Elem() 864 value, err := ToInt(source) 865 if !IsNilPointerError(err) && err != nil { 866 return err 867 } 868 switch directType.Kind() { 869 case reflect.Uint8: 870 alignValue := uint8(value) 871 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 872 case reflect.Uint16: 873 alignValue := uint16(value) 874 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 875 case reflect.Uint32: 876 alignValue := uint32(value) 877 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 878 case reflect.Uint64: 879 alignValue := uint64(value) 880 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&alignValue)) 881 default: 882 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&value)) 883 } 884 return nil 885 886 case *float32, *float64: 887 directValue := reflect.Indirect(reflect.ValueOf(targetValuePointer)) 888 value, err := ToFloat(source) 889 if err != nil { 890 return err 891 } 892 directValue.SetFloat(value) 893 return nil 894 case **float32, **float64: 895 directType := reflect.TypeOf(targetValuePointer).Elem().Elem() 896 897 value, err := ToFloat(source) 898 if err != nil { 899 return err 900 } 901 if directType.Kind() == reflect.Float32 { 902 float32Value := float32(value) 903 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&float32Value)) 904 } else { 905 reflect.ValueOf(targetValuePointer).Elem().Set(reflect.ValueOf(&value)) 906 } 907 return nil 908 case *time.Time: 909 timeValue, err := ToTime(source, c.DateLayout) 910 if err != nil { 911 return err 912 } 913 *targetValuePointer = *timeValue 914 return nil 915 case **time.Time: 916 if source == nil { 917 return nil 918 } 919 timeValue, err := ToTime(source, c.DateLayout) 920 if err != nil { 921 return err 922 } 923 *targetValuePointer = timeValue 924 return nil 925 case *interface{}: 926 if converter, ok := GetConverter(target, source); ok { 927 return converter(target, source) 928 } 929 (*targetValuePointer) = source 930 return nil 931 932 case **interface{}: 933 if converter, ok := GetConverter(target, source); ok { 934 return converter(target, source) 935 } 936 (*targetValuePointer) = &source 937 return nil 938 939 default: 940 if converter, ok := GetConverter(target, source); ok { 941 return converter(target, source) 942 } 943 } 944 945 sourceValue := reflect.ValueOf(source) 946 if source == nil || !sourceValue.IsValid() || (sourceValue.CanSet() && sourceValue.IsNil()) { 947 return nil 948 } 949 targetValue := reflect.ValueOf(target) 950 targetIndirectValue := reflect.Indirect(targetValue) 951 if sourceValue.IsValid() { 952 if sourceValue.Type().AssignableTo(targetValue.Type()) { 953 targetIndirectValue.Set(sourceValue.Elem()) 954 return nil 955 } else if sourceValue.Type().AssignableTo(targetValue.Type().Elem()) && sourceValue.Kind() == targetValue.Type().Elem().Kind() { 956 targetValue.Elem().Set(sourceValue) 957 return nil 958 } 959 } 960 var targetIndirectPointerType = reflect.TypeOf(target).Elem() 961 if targetIndirectPointerType.Kind() == reflect.Ptr || targetIndirectPointerType.Kind() == reflect.Slice || targetIndirectPointerType.Kind() == reflect.Map { 962 targetIndirectPointerType = targetIndirectPointerType.Elem() 963 } 964 965 if targetIndirectValue.Kind() == reflect.Slice || targetIndirectPointerType.Kind() == reflect.Slice { 966 967 if sourceValue.Kind() == reflect.Ptr && sourceValue.Elem().Kind() == reflect.Slice { 968 sourceValue = sourceValue.Elem() 969 } 970 if sourceValue.Kind() == reflect.Ptr && sourceValue.IsNil() { 971 return nil 972 } 973 if sourceValue.Kind() == reflect.Slice { 974 if targetIndirectValue.Kind() == reflect.Map { 975 return c.assignConvertedMap(target, source, targetIndirectValue, targetIndirectPointerType) 976 } 977 return c.assignConvertedSlice(target, source, targetIndirectValue, targetIndirectPointerType) 978 } 979 } 980 if targetIndirectValue.Kind() == reflect.Map || targetIndirectPointerType.Kind() == reflect.Map { 981 sourceKind := DereferenceType(sourceValue.Type()).Kind() 982 if sourceKind == reflect.Map { 983 return c.assignConvertedMap(target, source, targetIndirectValue, targetIndirectPointerType) 984 } else if sourceKind == reflect.Struct { 985 if source == nil { 986 return nil 987 } 988 if sourceValue.Kind() == reflect.Ptr && sourceValue.IsNil() { 989 return nil 990 } 991 targetValue := reflect.ValueOf(target) 992 if !targetValue.CanInterface() { 993 return nil 994 } 995 return c.assignConvertedMapFromStruct(source, target, sourceValue) 996 997 } else if sourceKind == reflect.Slice { 998 componentType := DereferenceType(DiscoverComponentType(source)) 999 if componentType.ConvertibleTo(reflect.TypeOf(keyValue{})) { 1000 return c.assignConvertedStructSliceToMap(target, source) 1001 } else if componentType.Kind() == reflect.Map { 1002 return c.assignConvertedMapSliceToMap(target, source) 1003 } else if componentType.Kind() == reflect.Interface { 1004 return c.assignConvertedMapSliceToMap(target, source) 1005 } 1006 } 1007 1008 } else if targetIndirectValue.Kind() == reflect.Struct { 1009 timeValuePtr := tryExtractTime(target) 1010 if timeValuePtr != nil { 1011 if timeValue, err := ToTime(source, c.DateLayout); err == nil { 1012 return c.assignEmbeddedTime(target, timeValue) 1013 } 1014 } 1015 1016 sourceMap, err := ToMap(source) 1017 if err != nil { 1018 return fmt.Errorf("unable to convert %T to %T", source, target) 1019 } 1020 return c.assignConvertedStruct(target, sourceMap, targetIndirectValue, targetIndirectPointerType) 1021 1022 } else if targetIndirectPointerType.Kind() == reflect.Struct { 1023 structPointer := reflect.New(targetIndirectPointerType) 1024 inputMap, err := ToMap(source) 1025 if err != nil { 1026 return fmt.Errorf("unable transfer to %T, source should be a map but was %T(%v)", target, source, source) 1027 } 1028 if err = c.assignConvertedStruct(target, inputMap, structPointer.Elem(), targetIndirectPointerType); err != nil { 1029 return err 1030 } 1031 targetIndirectValue.Set(structPointer) 1032 return nil 1033 1034 } 1035 1036 if sourceValue.IsValid() && sourceValue.Type().AssignableTo(targetIndirectValue.Type()) { 1037 targetIndirectValue.Set(sourceValue) 1038 return nil 1039 } 1040 if sourceValue.IsValid() && sourceValue.Type().ConvertibleTo(targetIndirectValue.Type()) { 1041 converted := sourceValue.Convert(targetIndirectValue.Type()) 1042 targetIndirectValue.Set(converted) 1043 return nil 1044 } 1045 1046 targetDeRefType := DereferenceType(target) 1047 1048 for _, candidate := range numericTypes { 1049 if candidate.Kind() == targetDeRefType.Kind() { 1050 var pointerCount = CountPointers(target) 1051 var compatibleTarget = reflect.New(candidate) 1052 for i := 0; i < pointerCount-1; i++ { 1053 compatibleTarget = reflect.New(compatibleTarget.Type()) 1054 } 1055 if err := c.AssignConverted(compatibleTarget.Interface(), source); err == nil { 1056 targetValue := reflect.ValueOf(target) 1057 targetValue.Elem().Set(compatibleTarget.Elem().Convert(targetValue.Elem().Type())) 1058 return nil 1059 } 1060 1061 } 1062 } 1063 return fmt.Errorf("Unable to convert type %T into type %T\n\t%v", source, target, source) 1064 } 1065 1066 func (c *Converter) assignEmbeddedTime(target interface{}, source *time.Time) error { 1067 targetValue := reflect.ValueOf(target) 1068 structValue := targetValue 1069 if targetValue.Kind() == reflect.Ptr { 1070 structValue = reflect.Indirect(targetValue) 1071 } 1072 anonymous := structValue.Field(0) 1073 anonymous.Set(reflect.ValueOf(*source)) 1074 if targetValue.Kind() == reflect.Ptr { 1075 targetValue.Elem().Set(structValue) 1076 } 1077 return nil 1078 } 1079 1080 type keyValue struct { 1081 Key, Value interface{} 1082 } 1083 1084 func (c *Converter) assignConvertedStructSliceToMap(target, source interface{}) (err error) { 1085 mapType := DiscoverTypeByKind(target, reflect.Map) 1086 mapPointer := reflect.ValueOf(target) 1087 mapValueType := mapType.Elem() 1088 mapKeyType := mapType.Key() 1089 newMap := mapPointer.Elem() 1090 newMap.Set(reflect.MakeMap(mapType)) 1091 keyValueType := reflect.TypeOf(keyValue{}) 1092 ProcessSlice(source, func(item interface{}) bool { 1093 if item == nil { 1094 return true 1095 } 1096 item = reflect.ValueOf(DereferenceValue(item)).Convert(keyValueType).Interface() 1097 pair, ok := item.(keyValue) 1098 if !ok { 1099 return true 1100 } 1101 1102 targetMapValuePointer := reflect.New(mapValueType) 1103 err = c.AssignConverted(targetMapValuePointer.Interface(), pair.Value) 1104 if err != nil { 1105 return false 1106 } 1107 targetMapKeyPointer := reflect.New(mapKeyType) 1108 err = c.AssignConverted(targetMapKeyPointer.Interface(), pair.Key) 1109 if err != nil { 1110 return false 1111 } 1112 var elementKey = targetMapKeyPointer.Elem() 1113 var elementValue = targetMapValuePointer.Elem() 1114 1115 if elementKey.Type() != mapKeyType { 1116 if elementKey.Type().AssignableTo(mapKeyType) { 1117 elementKey = elementKey.Convert(mapKeyType) 1118 } 1119 } 1120 if !elementValue.Type().AssignableTo(newMap.Type().Elem()) { 1121 var compatibleValue = reflect.New(newMap.Type().Elem()) 1122 err = c.AssignConverted(compatibleValue.Interface(), elementValue.Interface()) 1123 if err != nil { 1124 return false 1125 } 1126 elementValue = compatibleValue.Elem() 1127 } 1128 newMap.SetMapIndex(elementKey, elementValue) 1129 return true 1130 }) 1131 return err 1132 } 1133 1134 //entryMapToKeyValue converts entry map into map 1135 func entryMapToKeyValue(entryMap map[string]interface{}) (key string, value interface{}, err error) { 1136 if len(entryMap) > 2 { 1137 return key, value, fmt.Errorf("map entry needs to have 2 elements but had: %v, %v", len(entryMap), entryMap) 1138 } 1139 1140 hasValue := false 1141 for k, v := range entryMap { 1142 if strings.ToLower(k) == "key" { 1143 key = AsString(v) 1144 continue 1145 } else if strings.ToLower(k) == "value" { 1146 hasValue = true 1147 value = v 1148 } 1149 } 1150 if key == "" { 1151 return key, value, fmt.Errorf("key is required in entryMap %v", entryMap) 1152 } 1153 if !hasValue && len(entryMap) == 2 { 1154 return key, value, fmt.Errorf("map entry needs to have key, value pair but had: %v", entryMap) 1155 } 1156 return key, value, nil 1157 } 1158 1159 func (c *Converter) assignConvertedMapSliceToMap(target, source interface{}) (err error) { 1160 mapType := DiscoverTypeByKind(target, reflect.Map) 1161 mapPointer := reflect.ValueOf(target) 1162 mapValueType := mapType.Elem() 1163 mapKeyType := mapType.Key() 1164 newMap := mapPointer.Elem() 1165 newMap.Set(reflect.MakeMap(mapType)) 1166 ProcessSlice(source, func(item interface{}) bool { 1167 if item == nil { 1168 return true 1169 } 1170 entryMap := AsMap(item) 1171 key, value, e := entryMapToKeyValue(entryMap) 1172 if e != nil { 1173 err = fmt.Errorf("unable to cast %T to %T", source, target) 1174 return false 1175 } 1176 targetMapValuePointer := reflect.New(mapValueType) 1177 err = c.AssignConverted(targetMapValuePointer.Interface(), value) 1178 if err != nil { 1179 return false 1180 } 1181 targetMapKeyPointer := reflect.New(mapKeyType) 1182 err = c.AssignConverted(targetMapKeyPointer.Interface(), key) 1183 if err != nil { 1184 return false 1185 } 1186 var elementKey = targetMapKeyPointer.Elem() 1187 var elementValue = targetMapValuePointer.Elem() 1188 1189 if elementKey.Type() != mapKeyType { 1190 if elementKey.Type().AssignableTo(mapKeyType) { 1191 elementKey = elementKey.Convert(mapKeyType) 1192 } 1193 } 1194 if !elementValue.Type().AssignableTo(newMap.Type().Elem()) { 1195 var compatibleValue = reflect.New(newMap.Type().Elem()) 1196 err = c.AssignConverted(compatibleValue.Interface(), elementValue.Interface()) 1197 if err != nil { 1198 return false 1199 } 1200 elementValue = compatibleValue.Elem() 1201 } 1202 newMap.SetMapIndex(elementKey, elementValue) 1203 return true 1204 }) 1205 return err 1206 } 1207 1208 func (c *Converter) assignConvertedMapFromStruct(source, target interface{}, sourceValue reflect.Value) error { 1209 if source == nil || !sourceValue.IsValid() { 1210 return nil 1211 } 1212 targetMap := AsMap(target) 1213 if targetMap == nil { 1214 return fmt.Errorf("target %T is not a map", target) 1215 } 1216 1217 return ProcessStruct(source, func(fieldType reflect.StructField, field reflect.Value) error { 1218 if !field.CanInterface() { 1219 return nil 1220 } 1221 value := field.Interface() 1222 if value == nil { 1223 return nil 1224 } 1225 if timeVal := tryExtractTime(value); timeVal != nil { 1226 value = timeVal.Format(time.RFC3339) 1227 } 1228 var fieldTarget interface{} 1229 if IsStruct(value) { 1230 aMap := make(map[string]interface{}) 1231 if err := c.AssignConverted(&aMap, value); err != nil { 1232 return err 1233 } 1234 fieldTarget = aMap 1235 1236 } else if IsSlice(value) { 1237 var componentType = DereferenceType(DiscoverComponentType(value)) 1238 if componentType.Kind() == reflect.Struct { 1239 var slice = make([]map[string]interface{}, 0) 1240 if err := c.AssignConverted(&slice, value); err != nil { 1241 return err 1242 } 1243 fieldTarget = slice 1244 } else { 1245 if _, isByteArray := value.([]byte); isByteArray { 1246 fieldTarget = value 1247 } else { 1248 var slice = make([]interface{}, 0) 1249 if err := c.AssignConverted(&slice, value); err != nil { 1250 return err 1251 } 1252 fieldTarget = slice 1253 } 1254 } 1255 } else if err := c.AssignConverted(&fieldTarget, value); err != nil { 1256 return err 1257 } 1258 1259 fieldName := fieldType.Name 1260 keyTag := strings.Trim(fieldType.Tag.Get(c.MappedKeyTag), `"`) 1261 1262 if keyTag != "" { 1263 key := strings.Split(keyTag, ",")[0] 1264 if key == "-" { 1265 return nil 1266 } 1267 fieldName = key 1268 } 1269 targetMap[fieldName] = fieldTarget 1270 return nil 1271 }) 1272 } 1273 1274 func tryExtractTime(value interface{}) *time.Time { 1275 1276 if timeVal, ok := value.(time.Time); ok { 1277 return &timeVal 1278 } 1279 if timeVal, ok := value.(*time.Time); ok && timeVal != nil { 1280 return timeVal 1281 } 1282 if !IsStruct(value) { 1283 return nil 1284 } 1285 1286 structOrPtrValue := reflect.ValueOf(value) 1287 structValue := structOrPtrValue 1288 if structOrPtrValue.Kind() == reflect.Ptr { 1289 structValue = reflect.Indirect(structOrPtrValue) 1290 } 1291 if structValue.Kind() == reflect.Ptr { 1292 structValue = reflect.ValueOf(DereferenceValue(structValue.Interface())) 1293 } 1294 1295 if !structValue.IsValid() { 1296 return nil 1297 } 1298 if structValue.NumField() > 1 { 1299 return nil 1300 } 1301 timeField, ok := structValue.Type().FieldByName("Time") 1302 if !ok || !timeField.Anonymous { 1303 return nil 1304 } 1305 timeValue := structValue.Field(timeField.Index[0]) 1306 if timeValue.CanAddr() { 1307 return tryExtractTime(timeValue.Addr().Interface()) 1308 } 1309 return tryExtractTime(timeValue.Interface()) 1310 } 1311 1312 //NewColumnConverter create a new converter, that has ability to convert map to struct using column mapping 1313 func NewColumnConverter(dateLayout string) *Converter { 1314 return &Converter{dateLayout, "column"} 1315 } 1316 1317 //NewConverter create a new converter, that has ability to convert map to struct, it uses keytag to identify source and dest of fields/keys 1318 func NewConverter(dateLayout, keyTag string) *Converter { 1319 if keyTag == "" { 1320 keyTag = "name" 1321 } 1322 return &Converter{dateLayout, keyTag} 1323 } 1324 1325 //DefaultConverter represents a default data structure converter 1326 var DefaultConverter = NewConverter("", "name") 1327 1328 //DereferenceValues replaces pointer to its value within a generic map or slice 1329 func DereferenceValues(source interface{}) interface{} { 1330 if IsMap(source) { 1331 var aMap = make(map[string]interface{}) 1332 _ = ProcessMap(source, func(key, value interface{}) bool { 1333 if value == nil { 1334 return true 1335 } 1336 aMap[AsString(key)] = DereferenceValue(value) 1337 1338 return true 1339 }) 1340 return aMap 1341 1342 } else if IsSlice(source) { 1343 var aSlice = make([]interface{}, 0) 1344 ProcessSlice(source, func(item interface{}) bool { 1345 aSlice = append(aSlice, DereferenceValue(item)) 1346 return true 1347 }) 1348 return aSlice 1349 1350 } 1351 return DereferenceValue(source) 1352 } 1353 1354 //DereferenceValue dereference passed in value 1355 func DereferenceValue(value interface{}) interface{} { 1356 if value == nil { 1357 return nil 1358 } 1359 var reflectValue reflect.Value 1360 switch actualValue := value.(type) { 1361 case reflect.Value: 1362 reflectValue = actualValue 1363 default: 1364 reflectValue = reflect.ValueOf(value) 1365 } 1366 for { 1367 if !reflectValue.IsValid() { 1368 break 1369 } 1370 1371 if !reflectValue.CanInterface() { 1372 break 1373 } 1374 if reflectValue.Type().Kind() != reflect.Ptr { 1375 break 1376 } 1377 1378 reflectValue = reflectValue.Elem() 1379 } 1380 1381 var result interface{} 1382 if reflectValue.IsValid() && reflectValue.CanInterface() { 1383 result = reflectValue.Interface() 1384 } 1385 1386 if result != nil && (IsMap(result) || IsSlice(result)) { 1387 return DereferenceValues(value) 1388 } 1389 return result 1390 } 1391 1392 //DereferenceType dereference passed in value 1393 func DereferenceType(value interface{}) reflect.Type { 1394 if value == nil { 1395 return nil 1396 } 1397 var reflectType reflect.Type 1398 reflectValue, ok := value.(reflect.Value) 1399 if ok { 1400 reflectType = reflectValue.Type() 1401 } else if reflectType, ok = value.(reflect.Type); !ok { 1402 reflectType = reflect.TypeOf(value) 1403 } 1404 1405 for { 1406 if reflectType.Kind() != reflect.Ptr { 1407 break 1408 } 1409 reflectType = reflectType.Elem() 1410 } 1411 1412 return reflectType 1413 } 1414 1415 //CountPointers count pointers to undelying non pointer type 1416 func CountPointers(value interface{}) int { 1417 if value == nil { 1418 return 0 1419 } 1420 var result = 0 1421 reflectType, ok := value.(reflect.Type) 1422 if !ok { 1423 reflectType = reflect.TypeOf(value) 1424 } 1425 1426 for { 1427 if reflectType.Kind() != reflect.Ptr { 1428 break 1429 } 1430 result++ 1431 reflectType = reflectType.Elem() 1432 } 1433 1434 return result 1435 } 1436 1437 func initAnonymousStruct(aStruct interface{}) { 1438 structValue := DiscoverValueByKind(reflect.ValueOf(aStruct), reflect.Struct) 1439 structType := structValue.Type() 1440 for i := 0; i < structType.NumField(); i++ { 1441 fieldType := structType.Field(i) 1442 if !fieldType.Anonymous { 1443 continue 1444 } 1445 field := structValue.Field(i) 1446 if !IsStruct(field) { 1447 continue 1448 } 1449 1450 var aStruct interface{} 1451 if fieldType.Type.Kind() == reflect.Ptr { 1452 if field.IsNil() { 1453 if !field.CanSet() { 1454 continue 1455 } 1456 structValue.Field(i).Set(reflect.New(fieldType.Type.Elem())) 1457 } 1458 aStruct = field.Interface() 1459 } else { 1460 if !field.CanAddr() { 1461 continue 1462 } 1463 aStruct = field.Addr().Interface() 1464 } 1465 initAnonymousStruct(aStruct) 1466 } 1467 }