github.com/influx6/npkg@v0.8.8/nreflect/reflection.go (about) 1 package nreflect 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "strings" 8 ) 9 10 // ErrInvalid is returned when a type fails certain conditions. 11 var ErrInvalid = errors.New("invalid types, failed conditions") 12 13 // ErrPanic is returned when a panic happens. 14 var ErrPanic = errors.New("panic occured") 15 16 // ErrNotFunction is returned when the type is not a reflect.Func. 17 var ErrNotFunction = errors.New("Not A Function Type") 18 19 // IsFuncType returns true/false if the interface provided is a func type. 20 func IsFuncType(elem interface{}) bool { 21 _, err := FuncType(elem) 22 if err != nil { 23 return false 24 } 25 return true 26 } 27 28 // TypeValidation defines a function which validates a 29 // a given set against some condition. 30 type TypeValidation func([]reflect.Type) error 31 32 // AreaValidation defines a function which validates a 33 // a given set against some condition. 34 type AreaValidation func(arguments []reflect.Type, returns []reflect.Type) error 35 36 // ValidateFuncArea validates giving function arguments and returns types against AreaValidation 37 // functions. 38 func ValidateFuncArea(fn interface{}, conditions ...AreaValidation) error { 39 if len(conditions) == 0 { 40 return nil 41 } 42 43 funcTl, err := FuncType(fn) 44 if err != nil { 45 return err 46 } 47 48 args, err := getFuncArgumentsType(funcTl) 49 if err != nil { 50 return err 51 } 52 53 rets, err := getFuncReturnsType(funcTl) 54 if err != nil { 55 return err 56 } 57 58 for _, cond := range conditions { 59 if err = cond(args, rets); err != nil { 60 return err 61 } 62 } 63 64 return nil 65 } 66 67 // TypeName returns the original typename of giving target. 68 func TypeName(t interface{}) string { 69 var ref = reflect.ValueOf(t) 70 if ref.Kind() == reflect.Ptr { 71 ref = ref.Elem() 72 } 73 return ref.Type().Name() 74 } 75 76 func NameOf(obj interface{}) string { 77 name, ok := obj.(string) 78 if ok { 79 return name 80 } 81 return nameOfType(reflect.TypeOf(obj)) 82 } 83 84 func nameOfType(t reflect.Type) string { 85 stars := "" 86 if t == nil { 87 return "nil" 88 } 89 90 for t.Kind() == reflect.Ptr { 91 stars += "*" 92 t = t.Elem() 93 } 94 95 if t.Kind() == reflect.Interface { 96 stars = "" 97 } 98 return t.PkgPath() + "/" + stars + t.Name() 99 } 100 101 // ValidateFunc validates giving function arguments and returns types against TypeValidation 102 // functions. 103 func ValidateFunc(fn interface{}, argRules, returnRules []TypeValidation) error { 104 funcTl, err := FuncType(fn) 105 if err != nil { 106 return err 107 } 108 109 args, err := getFuncArgumentsType(funcTl) 110 if err != nil { 111 return err 112 } 113 114 for _, cond := range argRules { 115 if err = cond(args); err != nil { 116 return err 117 } 118 } 119 120 rets, err := getFuncReturnsType(funcTl) 121 if err != nil { 122 return err 123 } 124 125 for _, cond := range returnRules { 126 if err = cond(rets); err != nil { 127 return err 128 } 129 } 130 131 return nil 132 } 133 134 // CallFuncType attempts to call a giving function with provided arguments 135 // assuming all of them match the ff: 136 // 1. Exected number of arguments 137 // 2. Expected type of arguments 138 // It returns an error if not possible or returns the response for calling said 139 // function or if type is not a function. 140 // Note that the function call follows some rules: 141 // 1. If the function expects no arguments and some is supplied, 142 // they will be ignored. 143 func CallFunc(fn interface{}, args ...interface{}) (res []interface{}, err error) { 144 var funcTl reflect.Type 145 var funcVl reflect.Value 146 147 funcTl, err = FuncType(fn) 148 if err != nil { 149 return 150 } 151 152 res = make([]interface{}, funcTl.NumOut()) 153 154 funcVl, err = FuncValue(fn) 155 if err != nil { 156 return 157 } 158 159 if funcTl.NumIn() == 0 { 160 for index, item := range funcVl.Call(nil) { 161 res[index] = item.Interface() 162 } 163 return 164 } 165 166 argLen := len(args) 167 argValues := make([]reflect.Value, len(args)) 168 for index, arg := range args { 169 argValues[index] = reflect.ValueOf(arg) 170 } 171 172 if funcTl.NumIn() == 1 { 173 if funcTl.IsVariadic() && len(args) == 0 { 174 for index, item := range funcVl.CallSlice(nil) { 175 res[index] = item.Interface() 176 } 177 return 178 } 179 180 for index, item := range funcVl.Call(argValues) { 181 res[index] = item.Interface() 182 } 183 return 184 } 185 186 // if argument and expected are not equal in length 187 // and the last is variadic, we can treat has providing 188 // a nil towards that part. 189 if argLen != funcTl.NumIn() { 190 last := funcTl.NumIn() - 1 191 argItem := funcTl.In(last) 192 if argItem.IsVariadic() && argLen == last { 193 for index, item := range funcVl.Call(argValues) { 194 res[index] = item.Interface() 195 } 196 return 197 } else { 198 err = errors.New("argument length does not match number of wanted") 199 return 200 } 201 } 202 203 for i := 0; i < funcTl.NumIn(); i++ { 204 item := funcTl.In(i) 205 inarg := argValues[i] 206 207 canSet, mustConvert := CanSetFor(item, inarg) 208 if !canSet { 209 err = fmt.Errorf("argument at %d does not match function argument at postion", i) 210 return 211 } 212 213 if mustConvert { 214 converted, err2 := Convert(item, inarg) 215 if err2 != nil { 216 err = err2 217 return 218 } 219 220 argValues[i] = converted 221 } 222 } 223 224 if funcTl.IsVariadic() { 225 for index, item := range funcVl.CallSlice(argValues) { 226 res[index] = item.Interface() 227 } 228 return 229 } 230 231 for index, item := range funcVl.Call(argValues) { 232 res[index] = item.Interface() 233 } 234 235 return 236 } 237 238 // FuncValue return the Function reflect.Value of the provided function else 239 // returns a non-nil error. 240 func FuncValue(elem interface{}) (reflect.Value, error) { 241 tl := reflect.ValueOf(elem) 242 243 if tl.Kind() == reflect.Ptr { 244 tl = tl.Elem() 245 } 246 247 if tl.Kind() != reflect.Func { 248 return reflect.Value{}, ErrNotFunction 249 } 250 return tl, nil 251 } 252 253 // FuncType return the Function reflect.Type of the provided function else 254 // returns a non-nil error. 255 func FuncType(elem interface{}) (reflect.Type, error) { 256 tl := reflect.TypeOf(elem) 257 258 if tl.Kind() == reflect.Ptr { 259 tl = tl.Elem() 260 } 261 262 if tl.Kind() != reflect.Func { 263 return nil, ErrNotFunction 264 } 265 266 return tl, nil 267 } 268 269 // MatchElement attempts to validate that both element are equal in type and value. 270 func MatchElement(me interface{}, other interface{}, allowFunctions bool) bool { 271 meType := reflect.TypeOf(me) 272 otherType := reflect.TypeOf(other) 273 274 // if one is pointer, then both must be. 275 if meType.Kind() == reflect.Ptr && otherType.Kind() != reflect.Ptr { 276 return false 277 } 278 279 // if one is pointer, then both must be. 280 if otherType.Kind() == reflect.Ptr && meType.Kind() != reflect.Ptr { 281 return false 282 } 283 284 if meType.Kind() == reflect.Ptr { 285 meType = meType.Elem() 286 } 287 288 if otherType.Kind() == reflect.Ptr { 289 otherType = otherType.Elem() 290 } 291 292 if meType.Kind() == reflect.Func { 293 if allowFunctions { 294 return MatchFunction(me, other) 295 } 296 297 return false 298 } 299 300 if otherType.AssignableTo(meType) { 301 return true 302 } 303 304 return true 305 } 306 307 // MatchFunction attempts to validate if giving types are functions and 308 // exactly match in arguments and returns. 309 func MatchFunction(me interface{}, other interface{}) bool { 310 meType := reflect.TypeOf(me) 311 otherType := reflect.TypeOf(other) 312 313 // if one is pointer, then both must be. 314 if meType.Kind() == reflect.Ptr && otherType.Kind() != reflect.Ptr { 315 return false 316 } 317 318 // if one is pointer, then both must be. 319 if otherType.Kind() == reflect.Ptr && meType.Kind() != reflect.Ptr { 320 return false 321 } 322 323 if meType.Kind() == reflect.Ptr { 324 meType = meType.Elem() 325 } 326 327 if otherType.Kind() == reflect.Ptr { 328 otherType = otherType.Elem() 329 } 330 331 if meType.Kind() != reflect.Func { 332 return false 333 } 334 335 if otherType.Kind() != reflect.Func { 336 return false 337 } 338 339 if otherType.NumIn() != meType.NumIn() { 340 return false 341 } 342 343 if otherType.NumOut() != meType.NumOut() { 344 return false 345 } 346 347 for i := 0; i < meType.NumIn(); i++ { 348 item := meType.In(i) 349 otherItem := otherType.In(i) 350 if item.Kind() != reflect.Func && !MatchElement(item, otherItem, true) { 351 return false 352 } 353 354 if item.Kind() == reflect.Func && !MatchFunction(item, otherItem) { 355 return false 356 } 357 } 358 359 for i := 0; i < meType.NumOut(); i++ { 360 item := meType.Out(i) 361 otherItem := otherType.Out(i) 362 if item.Kind() != reflect.Func && !MatchElement(item, otherItem, true) { 363 return false 364 } 365 366 if item.Kind() == reflect.Func && !MatchFunction(item, otherItem) { 367 return false 368 } 369 } 370 371 return true 372 } 373 374 // TypeAndFields returns the type of the giving element and a slice of 375 // all composed types. 376 func TypeAndFields(elem interface{}) (reflect.Type, []reflect.Type, error) { 377 tl := reflect.ValueOf(elem) 378 379 if tl.Kind() == reflect.Ptr { 380 tl = tl.Elem() 381 } 382 383 if tl.Kind() != reflect.Struct { 384 return nil, nil, ErrNotStruct 385 } 386 387 var embeded []reflect.Type 388 389 for ind := 0; ind < tl.NumField(); ind++ { 390 item := tl.Field(ind).Type() 391 embeded = append(embeded, item) 392 } 393 394 return tl.Type(), embeded, nil 395 } 396 397 var internalTypes = []string{ 398 "string", "int", "int64", "int32", "float32", 399 "float64", "bool", "char", 400 "rune", "byte", 401 } 402 403 // FieldType defines a struct which holds details the name and package which 404 // a giving field belongs to. 405 type FieldType struct { 406 TypeName string `json:"field_type"` 407 Pkg string `json:"ngpkg"` 408 } 409 410 // ExternalTypeNames returns the name and field names of the provided 411 // elem which must be a struct, excluding all internal types. 412 func ExternalTypeNames(elem interface{}) (FieldType, []FieldType, error) { 413 tl := reflect.TypeOf(elem) 414 415 if tl.Kind() == reflect.Ptr { 416 tl = tl.Elem() 417 } 418 419 if tl.Kind() == reflect.Interface { 420 tl = tl.Elem() 421 } 422 423 if tl.Kind() != reflect.Struct { 424 return FieldType{}, nil, ErrNotStruct 425 } 426 427 var item FieldType 428 item.TypeName = tl.Name() 429 item.Pkg = tl.PkgPath() 430 431 var embeded []FieldType 432 433 { 434 fieldLoop: 435 for ind := 0; ind < tl.NumField(); ind++ { 436 item := tl.Field(ind).Type 437 438 for _, except := range internalTypes { 439 if except == item.Name() { 440 continue fieldLoop 441 } 442 } 443 444 if item.Name() == "" { 445 if item.Kind() == reflect.Slice || item.Kind() == reflect.Array || item.Kind() == reflect.Interface { 446 for _, except := range internalTypes { 447 if except == item.Elem().Name() { 448 continue fieldLoop 449 } 450 } 451 452 embeded = append(embeded, FieldType{ 453 TypeName: item.Elem().Name(), 454 Pkg: item.Elem().PkgPath(), 455 }) 456 } 457 458 continue 459 } 460 461 embeded = append(embeded, FieldType{ 462 TypeName: item.Name(), 463 Pkg: item.PkgPath(), 464 }) 465 } 466 } 467 468 return item, embeded, nil 469 } 470 471 // HasArgumentSize return true/false to indicate if the function type has the 472 // size of arguments. It will return false if the interface is not a function 473 // type. 474 func HasArgumentSize(elem interface{}, len int) bool { 475 tl := reflect.TypeOf(elem) 476 477 if tl.Kind() == reflect.Ptr { 478 tl = tl.Elem() 479 } 480 481 if tl.Kind() != reflect.Func { 482 return false 483 } 484 485 if tl.NumIn() != len { 486 return false 487 } 488 489 return true 490 } 491 492 // GetFuncReturnsType returns the returns type of function which should be 493 // a function type,else returns a non-nil error. 494 func GetFuncReturnsType(elem interface{}) ([]reflect.Type, error) { 495 tl := reflect.TypeOf(elem) 496 if tl.Kind() == reflect.Ptr { 497 tl = tl.Elem() 498 } 499 500 if tl.Kind() != reflect.Func { 501 return nil, ErrNotFunction 502 } 503 504 return getFuncReturnsType(tl) 505 } 506 507 func getFuncReturnsType(tl reflect.Type) ([]reflect.Type, error) { 508 totalFields := tl.NumOut() 509 if totalFields == 0 { 510 return nil, nil 511 } 512 513 input := make([]reflect.Type, 0, totalFields) 514 for i := 0; i < totalFields; i++ { 515 indElem := tl.Out(i) 516 input = append(input, indElem) 517 } 518 return input, nil 519 } 520 521 // GetFuncArgumentsType returns the arguments type of function which should be 522 // a function type,else returns a non-nil error. 523 func GetFuncArgumentsType(elem interface{}) ([]reflect.Type, error) { 524 tl := reflect.TypeOf(elem) 525 if tl.Kind() == reflect.Ptr { 526 tl = tl.Elem() 527 } 528 529 if tl.Kind() != reflect.Func { 530 return nil, ErrNotFunction 531 } 532 533 return getFuncArgumentsType(tl) 534 } 535 536 func getFuncArgumentsType(tl reflect.Type) ([]reflect.Type, error) { 537 totalFields := tl.NumIn() 538 if totalFields == 0 { 539 return nil, nil 540 } 541 542 input := make([]reflect.Type, 0, totalFields) 543 for i := 0; i < totalFields; i++ { 544 indElem := tl.In(i) 545 input = append(input, indElem) 546 } 547 return input, nil 548 } 549 550 // MatchFuncArgumentTypeWithValues validates specific values matches the elems 551 // function arguments. 552 func MatchFuncArgumentTypeWithValues(elem interface{}, vals []reflect.Value) int { 553 ma, err := GetFuncArgumentsType(elem) 554 if err != nil { 555 return -1 556 } 557 558 if len(ma) != len(vals) { 559 return -1 560 } 561 562 for index, item := range ma { 563 val := vals[index] 564 565 if ok, _ := CanSetFor(item, val); !ok { 566 return index 567 } 568 } 569 570 return -1 571 } 572 573 // StrictCanSetForType checks if a val reflect.Type can be used for the target type. 574 // It returns true/false if value matches the expected type and another true/false 575 // if the value can be converted to the expected type. 576 // Difference between this version and the other CanSet is that, it returns 577 // only true/false for the Assignability of the types and not based on the Assignability 578 // and convertibility. 579 func StrictCanSetForType(target, val reflect.Type) (canSet bool, mustConvert bool) { 580 if val.AssignableTo(target) { 581 canSet = true 582 } 583 584 if val.ConvertibleTo(target) { 585 mustConvert = true 586 } 587 588 return 589 } 590 591 // IsStrictlyAssignableType returns true/false if the element(elem) is of 592 // for ref type. 593 func IsStrictlyAssignableType(ref reflect.Type, elem reflect.Type) bool { 594 canset, _ := CanSetForType(ref, elem) 595 return canset 596 } 597 598 // IsStrictlyAssignable returns true/false if the element(elem) can be used for 599 // for ref type. 600 func IsStrictlyAssignable(ref reflect.Type, elem reflect.Value) bool { 601 canset, _ := CanSetFor(ref, elem) 602 return canset 603 } 604 605 // IsSettableType returns true/false if the element(elem) can be used for 606 // for ref type. 607 func IsSettableType(ref reflect.Type, elem reflect.Type) bool { 608 canset, canConvert := CanSetForType(ref, elem) 609 return canset || canConvert 610 } 611 612 // IsSettable returns true/false if the element(elem) can be used for 613 // for ref type. 614 func IsSettable(ref reflect.Type, elem reflect.Value) bool { 615 canset, canConvert := CanSetFor(ref, elem) 616 return canset || canConvert 617 } 618 619 // CanSetForType checks if a val reflect.Type can be used for the target type. 620 // It returns true bool, where the first returns if the value can be used and if 621 // it must be converted into the type first. 622 func CanSetForType(target, val reflect.Type) (canSet bool, mustConvert bool) { 623 if val.AssignableTo(target) { 624 canSet = true 625 return 626 } 627 628 if val.ConvertibleTo(target) { 629 canSet = true 630 mustConvert = true 631 return 632 } 633 634 return 635 } 636 637 // CanSetFor checks if the giving val can be set in the place of the target type. 638 // It returns true bool, where the first returns if the value can be used and if 639 // it must be converted into the type first. 640 func CanSetFor(target reflect.Type, val reflect.Value) (canSet bool, mustConvert bool) { 641 valType := val.Type() 642 643 if valType.AssignableTo(target) { 644 canSet = true 645 return 646 } 647 648 if valType.ConvertibleTo(target) { 649 canSet = true 650 mustConvert = true 651 return 652 } 653 654 return 655 } 656 657 // Convert takes a val and converts it into the target type provided if possible. 658 func Convert(target reflect.Type, val reflect.Value) (reflect.Value, error) { 659 valType := val.Type() 660 661 if !valType.ConvertibleTo(target) { 662 return reflect.Value{}, errors.New("Can not convert type") 663 } 664 665 return val.Convert(target), nil 666 } 667 668 // MakeValueFor makes a new reflect.Value for the reflect.Type. 669 func MakeValueFor(t reflect.Type) reflect.Value { 670 mtl := reflect.New(t) 671 672 if t.Kind() != reflect.Ptr && mtl.Kind() == reflect.Ptr { 673 mtl = mtl.Elem() 674 } 675 676 return mtl 677 } 678 679 // MakeArgumentsValues takes a list of reflect.Types and returns a new version of 680 // those types, ensuring to dereference if it receives a pointer reflect.Type. 681 func MakeArgumentsValues(args []reflect.Type) []reflect.Value { 682 var inputs []reflect.Value 683 684 for _, tl := range args { 685 inputs = append(inputs, MakeValueFor(tl)) 686 } 687 688 return inputs 689 } 690 691 // InterfaceFromValues returns a list of interfaces representing the concrete 692 // values within the lists of reflect.Value types. 693 func InterfaceFromValues(vals []reflect.Value) []interface{} { 694 var data []interface{} 695 696 for _, val := range vals { 697 if val.Kind() == reflect.Ptr { 698 val = val.Elem() 699 } 700 701 data = append(data, val.Interface()) 702 } 703 704 return data 705 } 706 707 //============================================================================== 708 709 // ErrNotStruct is returned when the reflect type is not a struct. 710 var ErrNotStruct = errors.New("Not a struct type") 711 712 // Field defines a specific tag field with its details from a giving struct. 713 type Field struct { 714 Index int 715 Name string 716 Tag string 717 NameLC string 718 TypeName string 719 Type reflect.Type 720 Value reflect.Value 721 IsSlice bool 722 IsArray bool 723 IsFunc bool 724 IsPointer bool 725 IsInterface bool 726 IsMap bool 727 IsChan bool 728 IsStruct bool 729 } 730 731 // Fields defines a lists of Field instances. 732 type Fields []Field 733 734 // GetTagFields retrieves all fields of the giving elements with the giving tag 735 // type. 736 func GetTagFields(elem interface{}, tag string, allowNaturalNames bool) (Fields, error) { 737 if !IsStruct(elem) { 738 return nil, ErrNotStruct 739 } 740 741 tl := reflect.TypeOf(elem) 742 tlVal := reflect.ValueOf(elem) 743 744 if tl.Kind() == reflect.Ptr { 745 tl = tl.Elem() 746 } 747 748 if tlVal.Kind() == reflect.Ptr { 749 if tlVal.IsNil() { 750 return nil, errors.New("invalid value: must be non-nil struct") 751 } 752 753 tlVal = tlVal.Elem() 754 } 755 756 var fields Fields 757 758 for i := 0; i < tl.NumField(); i++ { 759 field := tl.Field(i) 760 761 // Get the specified tag from this field if it exists. 762 tagVal := strings.TrimSpace(field.Tag.Get(tag)) 763 764 // If its a - item in the tag then skip or if its an empty string. 765 if tagVal == "-" { 766 continue 767 } 768 769 if !allowNaturalNames && tagVal == "" { 770 continue 771 } 772 773 if tagVal == "" { 774 tagVal = strings.ToLower(field.Name) 775 } 776 777 fields = append(fields, Field{ 778 Index: i, 779 Tag: tagVal, 780 Name: field.Name, 781 Type: field.Type, 782 Value: tlVal.Field(i), 783 TypeName: field.Type.Name(), 784 NameLC: strings.ToLower(field.Name), 785 IsMap: field.Type.Kind() == reflect.Map, 786 IsFunc: field.Type.Kind() == reflect.Func, 787 IsChan: field.Type.Kind() == reflect.Chan, 788 IsSlice: field.Type.Kind() == reflect.Slice, 789 IsArray: field.Type.Kind() == reflect.Array, 790 IsStruct: field.Type.Kind() == reflect.Struct, 791 IsInterface: field.Type.Kind() == reflect.Interface, 792 IsPointer: field.Type.Kind() == reflect.UnsafePointer, 793 }) 794 } 795 796 return fields, nil 797 } 798 799 // GetFieldByTagAndValue returns a giving struct field which has giving tag and value pair. 800 func GetFieldByTagAndValue(elem interface{}, tag string, value string) (reflect.StructField, error) { 801 if !IsStruct(elem) { 802 return reflect.StructField{}, ErrNotStruct 803 } 804 805 tl := reflect.TypeOf(elem) 806 if tl.Kind() == reflect.Ptr { 807 tl = tl.Elem() 808 } 809 810 for i := 0; i < tl.NumField(); i++ { 811 field := tl.Field(i) 812 if field.Tag.Get(tag) == value { 813 return field, nil 814 } 815 } 816 817 return reflect.StructField{}, ErrNoFieldWithTagFound 818 } 819 820 // GetFields retrieves all fields of the giving elements with the giving tag 821 // type. 822 func GetFields(elem interface{}) (Fields, error) { 823 if !IsStruct(elem) { 824 return nil, ErrNotStruct 825 } 826 827 tl := reflect.TypeOf(elem) 828 tlVal := reflect.ValueOf(elem) 829 830 if tl.Kind() == reflect.Ptr { 831 tl = tl.Elem() 832 } 833 834 if tlVal.Kind() == reflect.Ptr { 835 if tlVal.IsNil() { 836 return nil, errors.New("invalid value: must be non-nil struct") 837 } 838 839 tlVal = tlVal.Elem() 840 } 841 842 var fields Fields 843 844 for i := 0; i < tl.NumField(); i++ { 845 field := tl.Field(i) 846 fieldVal := Field{ 847 Index: i, 848 Name: field.Name, 849 Type: field.Type, 850 Value: tlVal.Field(i), 851 TypeName: field.Type.Name(), 852 NameLC: strings.ToLower(field.Name), 853 IsMap: field.Type.Kind() == reflect.Map, 854 IsFunc: field.Type.Kind() == reflect.Func, 855 IsChan: field.Type.Kind() == reflect.Chan, 856 IsSlice: field.Type.Kind() == reflect.Slice, 857 IsArray: field.Type.Kind() == reflect.Array, 858 IsStruct: field.Type.Kind() == reflect.Struct, 859 IsInterface: field.Type.Kind() == reflect.Interface, 860 IsPointer: field.Type.Kind() == reflect.UnsafePointer, 861 } 862 863 fields = append(fields, fieldVal) 864 } 865 866 return fields, nil 867 } 868 869 // ToMap returns a map of the giving values from a struct using a provided 870 // tag to capture the needed values, it extracts those tags values out into 871 // a map. It returns an error if the element is not a struct. 872 func ToMap(tag string, elem interface{}, allowNaturalNames bool) (map[string]interface{}, error) { 873 // Collect the fields that match the giving tag. 874 fields, err := GetTagFields(elem, tag, allowNaturalNames) 875 if err != nil { 876 return nil, err 877 } 878 879 // If there exists no field matching the tag skip. 880 if len(fields) == 0 { 881 return nil, errors.New("No Tag Matches") 882 } 883 884 data := make(map[string]interface{}) 885 886 // Loop through the fields and set the appropriate value as needed. 887 for _, field := range fields { 888 if !field.Value.CanInterface() { 889 continue 890 } 891 892 itemType := field.Type 893 item := field.Value.Interface() 894 895 switch itemType.Kind() { 896 case reflect.Struct: 897 if subItem, err := ToMap(tag, item, allowNaturalNames); err == nil { 898 data[field.Tag] = subItem 899 } else { 900 data[field.Tag] = item 901 } 902 903 default: 904 data[field.Tag] = item 905 } 906 } 907 908 return data, nil 909 } 910 911 // MergeMap merges the key names of the provided map into the appropriate field 912 // place where the element has the provided tag. 913 func MergeMap(tag string, elem interface{}, values map[string]interface{}, allowAll bool) error { 914 915 // Collect the fields that match the giving tag. 916 fields, err := GetTagFields(elem, tag, allowAll) 917 if err != nil { 918 return err 919 } 920 921 // If there exists no field matching the tag skip. 922 if len(fields) == 0 { 923 return nil 924 } 925 926 tl := reflect.ValueOf(elem) 927 928 if tl.Kind() == reflect.Ptr { 929 tl = tl.Elem() 930 } 931 932 // Loop through the fields and set the appropriate value as needed. 933 for _, field := range fields { 934 935 item := values[field.Tag] 936 937 if item == nil { 938 continue 939 } 940 941 fl := tl.Field(field.Index) 942 943 // If we can't set this field, then skip. 944 if !fl.CanSet() { 945 continue 946 } 947 948 fl.Set(reflect.ValueOf(item)) 949 } 950 951 return nil 952 } 953 954 // IsStruct returns true/false if the elem provided is a type of struct. 955 func IsStruct(elem interface{}) bool { 956 mc := reflect.TypeOf(elem) 957 958 if mc.Kind() == reflect.Ptr { 959 mc = mc.Elem() 960 } 961 962 if mc.Kind() != reflect.Struct { 963 return false 964 } 965 966 return true 967 } 968 969 func IsTypePtr(me interface{}, other interface{}) bool { 970 var mc = reflect.TypeOf(me) 971 var oc = reflect.TypeOf(other) 972 return mc == oc 973 } 974 975 func IsSameName(me interface{}, other interface{}) bool { 976 return TypeName(me) == TypeName(other) 977 } 978 979 func IsSameTypeName(me interface{}, other interface{}) bool { 980 var mc = reflect.TypeOf(me) 981 var oc = reflect.TypeOf(other) 982 return nameOfType(mc) == nameOfType(oc) 983 } 984 985 func IsType(me interface{}, other interface{}) bool { 986 var mc = reflect.TypeOf(me) 987 if mc.Kind() == reflect.Ptr { 988 mc = mc.Elem() 989 } 990 991 var oc = reflect.TypeOf(other) 992 if oc.Kind() == reflect.Ptr { 993 oc = oc.Elem() 994 } 995 996 return mc == oc 997 } 998 999 // MakeNew returns a new version of the giving type, returning a nonpointer type. 1000 // If the type is not a struct then an error is returned. 1001 func MakeNew(elem interface{}) (interface{}, error) { 1002 mc := reflect.TypeOf(elem) 1003 1004 if mc.Kind() != reflect.Struct { 1005 return nil, ErrNotStruct 1006 } 1007 1008 return reflect.New(mc).Interface(), nil 1009 }