@@ -435,97 +435,7 @@ func getFakedValue(item interface{}, opts *options.Options) (reflect.Value, erro
435435 }
436436 return v , nil
437437 case reflect .Struct :
438- if structTypeProvider , f := opts .StructTypeProviders [t ]; f {
439- ft , err := structTypeProvider ()
440- return reflect .ValueOf (ft ), err
441- }
442- originalDataVal := reflect .ValueOf (item )
443- v := reflect .New (t ).Elem ()
444- if opts .MaxFieldDepthOption == 0 {
445- return v , nil
446- } else if opts .MaxFieldDepthOption > 0 {
447- opts .MaxFieldDepthOption --
448- defer func () { opts .MaxFieldDepthOption ++ }()
449- }
450- retry := 0 // error if cannot generate unique value after maxRetry tries
451- for i := 0 ; i < v .NumField (); i ++ {
452- if ! v .Field (i ).CanSet () {
453- continue // to avoid panic to set on unexported field in struct
454- }
455-
456- if _ , ok := opts .IgnoreFields [t .Field (i ).Name ]; ok {
457- continue
458- }
459-
460- if p , ok := opts .FieldProviders [t .Field (i ).Name ]; ok {
461- val , err := p ()
462- if err != nil {
463- return reflect.Value {}, fmt .Errorf ("custom provider for field %s: %w" , t .Field (i ).Name , err )
464- }
465- v .Field (i ).Set (reflect .ValueOf (val ))
466- continue
467- }
468-
469- tags := decodeTags (t , i , opts .TagName )
470- switch {
471- case tags .keepOriginal :
472- zero , err := isZero (reflect .ValueOf (item ).Field (i ))
473- if err != nil {
474- return reflect.Value {}, err
475- }
476- if zero {
477- err := setDataWithTag (v .Field (i ).Addr (), tags .fieldType , * opts )
478- if err != nil {
479- return reflect.Value {}, err
480- }
481- continue
482- }
483- v .Field (i ).Set (reflect .ValueOf (item ).Field (i ))
484- case tags .fieldType == "" :
485- val , err := getFakedValue (v .Field (i ).Interface (), opts )
486- if err != nil {
487- return reflect.Value {}, err
488- }
489-
490- if v .Field (i ).CanSet () {
491- if ! reflect .ValueOf (val ).IsZero () && val .CanConvert (v .Field (i ).Type ()) {
492- val = val .Convert (v .Field (i ).Type ())
493- v .Field (i ).Set (val )
494- }
495-
496- }
497- case tags .fieldType == SKIP :
498- data := originalDataVal .Field (i ).Interface ()
499- if v .CanSet () && data != nil {
500- v .Field (i ).Set (reflect .ValueOf (data ))
501- }
502- default :
503- err := setDataWithTag (v .Field (i ).Addr (), tags .fieldType , * opts )
504- if err != nil {
505- return reflect.Value {}, err
506- }
507- }
508-
509- if tags .unique {
510- if retry >= maxRetry {
511- return reflect.Value {}, fmt .Errorf (fakerErrors .ErrUniqueFailure , reflect .TypeOf (item ).Field (i ).Name )
512- }
513- value := v .Field (i ).Interface ()
514- uniqueVal , _ := uniqueValues .Load (tags .fieldType )
515- uniqueValArr , _ := uniqueVal .([]interface {})
516- if slice .ContainsValue (uniqueValArr , value ) { // Retry if unique value already found
517- i --
518- retry ++
519- continue
520- }
521- retry = 0
522- uniqueValues .Store (tags .fieldType , append (uniqueValArr , value ))
523- } else {
524- retry = 0
525- }
526-
527- }
528- return v , nil
438+ return getFakedValueForStruct (item , t , opts )
529439
530440 case reflect .String :
531441 res , err := randomString (opts .RandomStringLength , * opts )
@@ -639,6 +549,100 @@ func getFakedValue(item interface{}, opts *options.Options) (reflect.Value, erro
639549
640550}
641551
552+ func getFakedValueForStruct (item interface {}, t reflect.Type , opts * options.Options ) (reflect.Value , error ) {
553+ if structTypeProvider , f := opts .StructTypeProviders [t ]; f {
554+ ft , err := structTypeProvider ()
555+ return reflect .ValueOf (ft ), err
556+ }
557+ originalDataVal := reflect .ValueOf (item )
558+ v := reflect .New (t ).Elem ()
559+ if opts .MaxFieldDepthOption == 0 {
560+ return v , nil
561+ } else if opts .MaxFieldDepthOption > 0 {
562+ opts .MaxFieldDepthOption --
563+ defer func () { opts .MaxFieldDepthOption ++ }()
564+ }
565+ retry := 0 // error if cannot generate unique value after maxRetry tries
566+ for i := 0 ; i < v .NumField (); i ++ {
567+ if ! v .Field (i ).CanSet () {
568+ continue // to avoid panic to set on unexported field in struct
569+ }
570+
571+ if _ , ok := opts .IgnoreFields [t .Field (i ).Name ]; ok {
572+ continue
573+ }
574+
575+ if p , ok := opts .FieldProviders [t .Field (i ).Name ]; ok {
576+ val , err := p ()
577+ if err != nil {
578+ return reflect.Value {}, fmt .Errorf ("custom provider for field %s: %w" , t .Field (i ).Name , err )
579+ }
580+ v .Field (i ).Set (reflect .ValueOf (val ))
581+ continue
582+ }
583+
584+ tags := decodeTags (t , i , opts .TagName )
585+ switch {
586+ case tags .keepOriginal :
587+ zero , err := isZero (reflect .ValueOf (item ).Field (i ))
588+ if err != nil {
589+ return reflect.Value {}, err
590+ }
591+ if zero {
592+ err := setDataWithTag (v .Field (i ).Addr (), tags .fieldType , * opts )
593+ if err != nil {
594+ return reflect.Value {}, err
595+ }
596+ continue
597+ }
598+ v .Field (i ).Set (reflect .ValueOf (item ).Field (i ))
599+ case tags .fieldType == "" :
600+ val , err := getFakedValue (v .Field (i ).Interface (), opts )
601+ if err != nil {
602+ return reflect.Value {}, err
603+ }
604+
605+ if v .Field (i ).CanSet () {
606+ if ! reflect .ValueOf (val ).IsZero () && val .CanConvert (v .Field (i ).Type ()) {
607+ val = val .Convert (v .Field (i ).Type ())
608+ v .Field (i ).Set (val )
609+ }
610+
611+ }
612+ case tags .fieldType == SKIP :
613+ data := originalDataVal .Field (i ).Interface ()
614+ if v .CanSet () && data != nil {
615+ v .Field (i ).Set (reflect .ValueOf (data ))
616+ }
617+ default :
618+ err := setDataWithTag (v .Field (i ).Addr (), tags .fieldType , * opts )
619+ if err != nil {
620+ return reflect.Value {}, err
621+ }
622+ }
623+
624+ if tags .unique {
625+ if retry >= maxRetry {
626+ return reflect.Value {}, fmt .Errorf (fakerErrors .ErrUniqueFailure , reflect .TypeOf (item ).Field (i ).Name )
627+ }
628+ value := v .Field (i ).Interface ()
629+ uniqueVal , _ := uniqueValues .Load (tags .fieldType )
630+ uniqueValArr , _ := uniqueVal .([]interface {})
631+ if slice .ContainsValue (uniqueValArr , value ) { // Retry if unique value already found
632+ i --
633+ retry ++
634+ continue
635+ }
636+ retry = 0
637+ uniqueValues .Store (tags .fieldType , append (uniqueValArr , value ))
638+ } else {
639+ retry = 0
640+ }
641+
642+ }
643+ return v , nil
644+ }
645+
642646func isZero (field reflect.Value ) (bool , error ) {
643647 if field .Kind () == reflect .Map {
644648 return field .Len () == 0 , nil
0 commit comments