8
8
import java .lang .reflect .Field ;
9
9
import java .lang .reflect .ParameterizedType ;
10
10
import java .lang .reflect .Type ;
11
- import java .util .ArrayList ;
12
- import java .util .HashMap ;
13
- import java .util .List ;
14
- import java .util .Map ;
11
+ import java .util .*;
15
12
16
13
class Codegen {
17
14
final static Map <String , String > NATIVE_READS = new HashMap <String , String >() {{
@@ -55,34 +52,40 @@ private synchronized static Decoder gen(String cacheKey, Type type, Type[] typeA
55
52
} else {
56
53
clazz = (Class ) type ;
57
54
}
55
+ String source ;
56
+ if (clazz .isArray ()) {
57
+ source = genArray (clazz );
58
+ } else if (List .class .isAssignableFrom (clazz )) {
59
+ Class compType = (Class ) typeArgs [0 ];
60
+ if (clazz == List .class ) {
61
+ clazz = ArrayList .class ;
62
+ }
63
+ source = genList (clazz , compType );
64
+ } else {
65
+ source = genObject (clazz , cacheKey );
66
+ }
58
67
try {
59
68
CtClass ctClass = pool .makeClass (cacheKey );
60
69
ctClass .setInterfaces (new CtClass []{pool .get (Decoder .class .getName ())});
61
- String source ;
62
- if (clazz .isArray ()) {
63
- source = genArray (clazz );
64
- } else if (List .class .isAssignableFrom (clazz )) {
65
- Class compType = (Class ) typeArgs [0 ];
66
- if (clazz == List .class ) {
67
- clazz = ArrayList .class ;
68
- }
69
- source = genList (clazz , compType );
70
- } else {
71
- source = genObject (clazz );
72
- }
73
70
CtMethod method = CtNewMethod .make (source , ctClass );
74
71
ctClass .addMethod (method );
75
72
decoder = (Decoder ) ctClass .toClass ().newInstance ();
76
- HashMap <String , Decoder > newCache = new HashMap <>(cache );
77
- newCache .put (cacheKey , decoder );
78
- cache = newCache ;
73
+ addNewDecoder (cacheKey , decoder );
79
74
return decoder ;
80
75
} catch (Exception e ) {
76
+ System .err .println ("failed to generate encoder for: " + type + " with " + Arrays .toString (typeArgs ));
77
+ System .err .println (source );
81
78
throw new RuntimeException (e );
82
79
}
83
80
}
84
81
85
- private static String genObject (Class clazz ) {
82
+ public static void addNewDecoder (String cacheKey , Decoder decoder ) {
83
+ HashMap <String , Decoder > newCache = new HashMap <>(cache );
84
+ newCache .put (cacheKey , decoder );
85
+ cache = newCache ;
86
+ }
87
+
88
+ private static String genObject (Class clazz , String cacheKey ) {
86
89
Map <Integer , Object > map = new HashMap <>();
87
90
for (Field field : clazz .getFields ()) {
88
91
byte [] fieldName = field .getName ().getBytes ();
@@ -120,7 +123,7 @@ private static String genObject(Class clazz) {
120
123
Integer len = entry .getKey ();
121
124
append (lines , "case " + len + ": " );
122
125
Map <Byte , Object > current = (Map <Byte , Object >) entry .getValue ();
123
- addFieldDispatch (lines , len , 0 , current );
126
+ addFieldDispatch (lines , len , 0 , current , cacheKey );
124
127
append (lines , "break;" );
125
128
}
126
129
append (lines , "}" );
@@ -131,36 +134,45 @@ private static String genObject(Class clazz) {
131
134
return lines .toString ().replace ("{{clazz}}" , clazz .getName ());
132
135
}
133
136
134
- private static void addFieldDispatch (StringBuilder lines , int len , int i , Map <Byte , Object > current ) {
137
+ private static void addFieldDispatch (StringBuilder lines , int len , int i , Map <Byte , Object > current , String cacheKey ) {
135
138
for (Map .Entry <Byte , Object > entry : current .entrySet ()) {
136
139
Byte b = entry .getKey ();
137
140
append (lines , String .format ("if (field.at(%d)==%s) {" , i , b ));
138
141
if (i == len - 1 ) {
139
- Field field = (Field ) entry .getValue ();
140
- String fieldTypeName = field .getType ().getCanonicalName ();
141
- String nativeRead = NATIVE_READS .get (fieldTypeName );
142
- if (nativeRead == null ) {
143
- if (field .getGenericType () instanceof ParameterizedType ) {
144
- ParameterizedType pType = (ParameterizedType ) field .getGenericType ();
145
- Class arg1 = (Class ) pType .getActualTypeArguments ()[0 ];
146
- append (lines , String .format ("obj.%s = (%s)iter.read(\" %s\" , %s.class, %s.class);" ,
147
- field .getName (), fieldTypeName , TypeLiteral .generateCacheKey (field .getGenericType ()),
148
- fieldTypeName , arg1 .getName ()));
149
- } else {
150
- append (lines , String .format ("obj.%s = (%s)iter.read(%s.class);" ,
151
- field .getName (), fieldTypeName , fieldTypeName ));
152
- }
153
- } else {
154
- append (lines , String .format ("obj.%s = %s;" , field .getName (), nativeRead ));
155
- }
142
+ genField (lines , (Field ) entry .getValue (), cacheKey );
156
143
append (lines , "continue;" );
157
144
} else {
158
- addFieldDispatch (lines , len , i + 1 , (Map <Byte , Object >) entry .getValue ());
145
+ addFieldDispatch (lines , len , i + 1 , (Map <Byte , Object >) entry .getValue (), cacheKey );
159
146
}
160
147
append (lines , "}" );
161
148
}
162
149
}
163
150
151
+ private static void genField (StringBuilder lines , Field field , String cacheKey ) {
152
+ String fieldCacheKey = field .getName () + "@" + cacheKey ;
153
+ String fieldTypeName = field .getType ().getCanonicalName ();
154
+ String nativeRead = NATIVE_READS .get (fieldTypeName );
155
+ if (cache .containsKey (fieldCacheKey )) {
156
+ append (lines , String .format ("obj.%s = (%s)iter.read(\" %s\" , %s.class);" ,
157
+ field .getName (), fieldTypeName , fieldCacheKey , fieldTypeName ));
158
+ return ;
159
+ }
160
+ if (nativeRead == null ) {
161
+ if (field .getGenericType () instanceof ParameterizedType ) {
162
+ ParameterizedType pType = (ParameterizedType ) field .getGenericType ();
163
+ Class arg1 = (Class ) pType .getActualTypeArguments ()[0 ];
164
+ append (lines , String .format ("obj.%s = (%s)iter.read(\" %s\" , %s.class, %s.class);" ,
165
+ field .getName (), fieldTypeName , TypeLiteral .generateCacheKey (field .getGenericType ()),
166
+ fieldTypeName , arg1 .getName ()));
167
+ } else {
168
+ append (lines , String .format ("obj.%s = (%s)iter.read(%s.class);" ,
169
+ field .getName (), fieldTypeName , fieldTypeName ));
170
+ }
171
+ } else {
172
+ append (lines , String .format ("obj.%s = %s;" , field .getName (), nativeRead ));
173
+ }
174
+ }
175
+
164
176
private static String genArray (Class clazz ) {
165
177
Class compType = clazz .getComponentType ();
166
178
if (compType .isArray ()) {
0 commit comments