@@ -785,6 +785,7 @@ func (e *Encoder) isNotExistsField(head *opcode) bool {
785
785
func (e * Encoder ) optimizeAnonymousFields (head * opcode ) {
786
786
code := head
787
787
var prev * opcode
788
+ removedFields := map [* opcode ]struct {}{}
788
789
for {
789
790
if code .op == opStructEnd || code .op == opStructEndIndent {
790
791
break
@@ -798,7 +799,7 @@ func (e *Encoder) optimizeAnonymousFields(head *opcode) {
798
799
for i := 0 ; i < diff ; i ++ {
799
800
code .next .decOpcodeIndex ()
800
801
}
801
- linkPrevToNextField (prev , code )
802
+ linkPrevToNextField (code , removedFields )
802
803
code = prev
803
804
}
804
805
}
@@ -815,27 +816,30 @@ type structFieldPair struct {
815
816
linked bool
816
817
}
817
818
818
- func (e * Encoder ) anonymousStructFieldPairMap (typ * rtype , tags structTags , valueCode * opcode ) map [string ][]structFieldPair {
819
+ func (e * Encoder ) anonymousStructFieldPairMap (typ * rtype , tags structTags , named string , valueCode * opcode ) map [string ][]structFieldPair {
819
820
anonymousFields := map [string ][]structFieldPair {}
820
821
f := valueCode
821
822
var prevAnonymousField * opcode
823
+ removedFields := map [* opcode ]struct {}{}
822
824
for {
823
825
existsKey := tags .existsKey (f .displayKey )
824
826
op := f .op .headToAnonymousHead ()
825
- if op != f .op {
827
+ if existsKey && (f .next .op == opStructFieldPtrAnonymousHeadRecursive || f .next .op == opStructFieldAnonymousHeadRecursive ) {
828
+ // through
829
+ } else if op != f .op {
826
830
if existsKey {
827
831
f .op = opStructFieldAnonymousHead
828
- } else {
832
+ } else if named == "" {
829
833
f .op = op
830
834
}
831
- } else if f .op == opStructEnd {
835
+ } else if named == "" && f .op == opStructEnd {
832
836
f .op = opStructAnonymousEnd
833
837
} else if existsKey {
834
838
diff := f .nextField .displayIdx - f .displayIdx
835
839
for i := 0 ; i < diff ; i ++ {
836
840
f .nextField .decOpcodeIndex ()
837
841
}
838
- linkPrevToNextField (prevAnonymousField , f )
842
+ linkPrevToNextField (f , removedFields )
839
843
}
840
844
841
845
if f .displayKey == "" {
@@ -847,13 +851,14 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
847
851
continue
848
852
}
849
853
850
- anonymousFields [f .displayKey ] = append (anonymousFields [f .displayKey ], structFieldPair {
854
+ key := fmt .Sprintf ("%s.%s" , named , f .displayKey )
855
+ anonymousFields [key ] = append (anonymousFields [key ], structFieldPair {
851
856
prevField : prevAnonymousField ,
852
857
curField : f ,
853
858
isTaggedKey : f .isTaggedKey ,
854
859
})
855
860
if f .next != nil && f .nextField != f .next && f .next .op .codeType () == codeStructField {
856
- for k , v := range e .anonymousStructFieldPairMap (typ , tags , f .next ) {
861
+ for k , v := range e .anonymousStructFieldPairMap (typ , tags , named , f .next ) {
857
862
anonymousFields [k ] = append (anonymousFields [k ], v ... )
858
863
}
859
864
}
@@ -867,6 +872,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
867
872
}
868
873
869
874
func (e * Encoder ) optimizeConflictAnonymousFields (anonymousFields map [string ][]structFieldPair ) {
875
+ removedFields := map [* opcode ]struct {}{}
870
876
for _ , fieldPairs := range anonymousFields {
871
877
if len (fieldPairs ) == 1 {
872
878
continue
@@ -886,7 +892,8 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
886
892
for i := 0 ; i < diff ; i ++ {
887
893
fieldPair .curField .nextField .decOpcodeIndex ()
888
894
}
889
- linkPrevToNextField (fieldPair .prevField , fieldPair .curField )
895
+ removedFields [fieldPair .curField ] = struct {}{}
896
+ linkPrevToNextField (fieldPair .curField , removedFields )
890
897
}
891
898
fieldPair .linked = true
892
899
}
@@ -900,10 +907,11 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
900
907
fieldPair .curField .op = opStructFieldAnonymousHead
901
908
} else {
902
909
diff := fieldPair .curField .nextField .displayIdx - fieldPair .curField .displayIdx
910
+ removedFields [fieldPair .curField ] = struct {}{}
903
911
for i := 0 ; i < diff ; i ++ {
904
912
fieldPair .curField .nextField .decOpcodeIndex ()
905
913
}
906
- linkPrevToNextField (fieldPair .prevField , fieldPair . curField )
914
+ linkPrevToNextField (fieldPair .curField , removedFields )
907
915
}
908
916
fieldPair .linked = true
909
917
}
@@ -970,7 +978,17 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
970
978
}
971
979
972
980
if field .Anonymous {
973
- for k , v := range e .anonymousStructFieldPairMap (typ , tags , valueCode ) {
981
+ if valueCode .op == opPtr && valueCode .next .op == opStructFieldRecursive {
982
+ valueCode = valueCode .next
983
+ valueCode .decOpcodeIndex ()
984
+ ctx .decIndex ()
985
+ valueCode .op = opStructFieldPtrHeadRecursive
986
+ }
987
+ tagKey := ""
988
+ if tag .isTaggedKey {
989
+ tagKey = tag .key
990
+ }
991
+ for k , v := range e .anonymousStructFieldPairMap (typ , tags , tagKey , valueCode ) {
974
992
anonymousFields [k ] = append (anonymousFields [k ], v ... )
975
993
}
976
994
}
@@ -1015,6 +1033,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
1015
1033
code .next = fieldCode
1016
1034
code = e .structField (ctx , fieldCode , valueCode , tag )
1017
1035
prevField .nextField = fieldCode
1036
+ fieldCode .prevField = prevField
1018
1037
prevField = fieldCode
1019
1038
}
1020
1039
fieldIdx ++
@@ -1039,6 +1058,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
1039
1058
indent : ctx .indent ,
1040
1059
nextField : structEndCode ,
1041
1060
}
1061
+ structEndCode .prevField = head
1042
1062
ctx .incIndex ()
1043
1063
if ctx .withIndent {
1044
1064
head .op = opStructFieldHeadIndent
@@ -1056,14 +1076,13 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
1056
1076
1057
1077
if prevField != nil && prevField .nextField == nil {
1058
1078
prevField .nextField = structEndCode
1079
+ structEndCode .prevField = prevField
1059
1080
}
1060
1081
1061
1082
head .end = structEndCode
1062
1083
code .next = structEndCode
1063
-
1064
1084
e .optimizeConflictAnonymousFields (anonymousFields )
1065
1085
e .optimizeAnonymousFields (head )
1066
-
1067
1086
ret := (* opcode )(unsafe .Pointer (head ))
1068
1087
compiled .code = ret
1069
1088
0 commit comments