@@ -135,6 +135,14 @@ var (
135
135
genQNameRegex = regexp .MustCompile (`[A-Za-z_.]+` )
136
136
)
137
137
138
+ type genBuf struct {
139
+ buf []byte
140
+ }
141
+
142
+ func (x * genBuf ) s (s string ) * genBuf { x .buf = append (x .buf , s ... ); return x }
143
+ func (x * genBuf ) b (s []byte ) * genBuf { x .buf = append (x .buf , s ... ); return x }
144
+ func (x * genBuf ) v () string { return string (x .buf ) }
145
+
138
146
// genRunner holds some state used during a Gen run.
139
147
type genRunner struct {
140
148
w io.Writer // output
@@ -697,13 +705,17 @@ func (x *genRunner) enc(varname string, t reflect.Type) {
697
705
}
698
706
699
707
// check if
700
- // - type is RawExt, Raw
708
+ // - type is time.Time, RawExt, Raw
701
709
// - the type implements (Text|JSON|Binary)(Unm|M)arshal
702
710
x .linef ("%sm%s := z.EncBinary()" , genTempVarPfx , mi )
703
711
x .linef ("_ = %sm%s" , genTempVarPfx , mi )
704
712
x .line ("if false {" ) //start if block
705
713
defer func () { x .line ("}" ) }() //end if block
706
714
715
+ if t == timeTyp {
716
+ x .linef ("} else { r.EncodeTime(*%s)" , varname )
717
+ return
718
+ }
707
719
if t == rawTyp {
708
720
x .linef ("} else { z.EncRaw(%s)" , varname )
709
721
return
@@ -848,6 +860,29 @@ func (x *genRunner) encZero(t reflect.Type) {
848
860
}
849
861
}
850
862
863
+ func (x * genRunner ) encOmitEmptyLine (t2 reflect.StructField , varname string , buf * genBuf ) {
864
+ // smartly check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
865
+ // also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
866
+ switch t2 .Type .Kind () {
867
+ case reflect .Struct :
868
+ // fmt.Printf(">>>> structfield: omitempty: type: %s, field: %s\n", t2.Type.Name(), t2.Name)
869
+ buf .s ("true " )
870
+ varname2 := varname + "." + t2 .Name
871
+ for i , n := 0 , t2 .Type .NumField (); i < n ; i ++ {
872
+ f := t2 .Type .Field (i )
873
+ if f .PkgPath != "" { // unexported
874
+ continue
875
+ }
876
+ buf .s (" && " )
877
+ x .encOmitEmptyLine (f , varname2 , buf )
878
+ }
879
+ case reflect .Map , reflect .Slice , reflect .Array , reflect .Chan :
880
+ buf .s ("len(" ).s (varname ).s ("." ).s (t2 .Name ).s (") != 0" )
881
+ default :
882
+ buf .s (varname ).s ("." ).s (t2 .Name ).s (" != " ).s (x .genZeroValueR (t2 .Type ))
883
+ }
884
+ }
885
+
851
886
func (x * genRunner ) encStruct (varname string , rtid uintptr , t reflect.Type ) {
852
887
// Use knowledge from structfieldinfo (mbs, encodable fields. Ignore omitempty. )
853
888
// replicate code in kStruct i.e. for each field, deref type to non-pointer, and call x.enc on it
@@ -881,7 +916,7 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
881
916
continue
882
917
}
883
918
var t2 reflect.StructField
884
- var omitline string
919
+ var omitline genBuf
885
920
{
886
921
t2typ := t
887
922
varname3 := varname
@@ -900,21 +935,13 @@ func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
900
935
// do not include actual field in the omit line.
901
936
// that is done subsequently (right after - below).
902
937
if uint8 (ij + 1 ) < si .nis && t2typ .Kind () == reflect .Ptr {
903
- omitline += varname3 + " != nil && "
938
+ omitline .s (varname3 ).s (" != nil && " )
939
+ // omitline += varname3 + " != nil && "
904
940
}
905
941
}
906
942
}
907
- // never check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
908
- // also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
909
- switch t2 .Type .Kind () {
910
- case reflect .Struct :
911
- omitline += " true"
912
- case reflect .Map , reflect .Slice , reflect .Array , reflect .Chan :
913
- omitline += "len(" + varname + "." + t2 .Name + ") != 0"
914
- default :
915
- omitline += varname + "." + t2 .Name + " != " + x .genZeroValueR (t2 .Type )
916
- }
917
- x .linef ("%s[%v] = %s" , numfieldsvar , j , omitline )
943
+ x .encOmitEmptyLine (t2 , varname , & omitline )
944
+ x .linef ("%s[%v] = %s" , numfieldsvar , j , omitline .v ())
918
945
}
919
946
}
920
947
// x.linef("var %snn%s int", genTempVarPfx, i)
@@ -1163,14 +1190,18 @@ func (x *genRunner) dec(varname string, t reflect.Type) {
1163
1190
}
1164
1191
1165
1192
// check if
1166
- // - type is Raw, RawExt
1193
+ // - type is time.Time, Raw, RawExt
1167
1194
// - the type implements (Text|JSON|Binary)(Unm|M)arshal
1168
1195
mi := x .varsfx ()
1169
1196
x .linef ("%sm%s := z.DecBinary()" , genTempVarPfx , mi )
1170
1197
x .linef ("_ = %sm%s" , genTempVarPfx , mi )
1171
1198
x .line ("if false {" ) //start if block
1172
1199
defer func () { x .line ("}" ) }() //end if block
1173
1200
1201
+ if t == timeTyp {
1202
+ x .linef ("} else { *%v = r.DecodeTime()" , varname )
1203
+ return
1204
+ }
1174
1205
if t == rawTyp {
1175
1206
x .linef ("} else { *%v = z.DecRaw()" , varname )
1176
1207
return
@@ -1677,7 +1708,7 @@ func genImportPath(t reflect.Type) (s string) {
1677
1708
s = t .PkgPath ()
1678
1709
if genCheckVendor {
1679
1710
// HACK: always handle vendoring. It should be typically on in go 1.6, 1.7
1680
- s = stripVendor (s )
1711
+ s = genStripVendor (s )
1681
1712
}
1682
1713
return
1683
1714
}
@@ -1926,7 +1957,7 @@ func genInternalSortType(s string, elem bool) string {
1926
1957
panic ("sorttype: unexpected type: " + s )
1927
1958
}
1928
1959
1929
- func stripVendor (s string ) string {
1960
+ func genStripVendor (s string ) string {
1930
1961
// HACK: Misbehaviour occurs in go 1.5. May have to re-visit this later.
1931
1962
// if s contains /vendor/ OR startsWith vendor/, then return everything after it.
1932
1963
const vendorStart = "vendor/"
0 commit comments