protobuf
This commit is contained in:
@@ -360,6 +360,7 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
||||
}
|
||||
}
|
||||
objout.writeObjectE(value);
|
||||
offerWriter(out, objout);
|
||||
}
|
||||
|
||||
// ---------------------------------- 可定制方法 ----------------------------------
|
||||
@@ -375,6 +376,10 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
||||
return out;
|
||||
}
|
||||
|
||||
protected void offerWriter(W parent, W out) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
protected void setTag(EnMember member, int tag) {
|
||||
member.tag = tag;
|
||||
|
||||
@@ -28,16 +28,20 @@ import org.redkale.util.*;
|
||||
* @param <T> 序列化的数据类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
||||
public abstract class JsonDynEncoder<T> extends ObjectEncoder<JsonWriter, T> {
|
||||
|
||||
protected final Class typeClass;
|
||||
|
||||
protected final ObjectEncoder<JsonWriter, T> objectEncoder;
|
||||
protected final ObjectEncoder<JsonWriter, T> objectEncoderSelf;
|
||||
|
||||
protected JsonDynEncoder(final JsonFactory factory, Type type) {
|
||||
protected JsonDynEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
super(type);
|
||||
this.typeClass = (Class) type;
|
||||
this.factory = factory;
|
||||
this.objectEncoderSelf = objectEncoderSelf;
|
||||
this.members = objectEncoderSelf.getMembers();
|
||||
this.inited = true;
|
||||
factory.register(type, this);
|
||||
this.objectEncoder = factory.createObjectEncoder(type);
|
||||
}
|
||||
|
||||
protected static JsonDynEncoder generateDyncEncoder(
|
||||
@@ -70,11 +74,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
|
||||
JsonDynEncoder resultEncoder =
|
||||
(JsonDynEncoder) newClazz.getDeclaredConstructor(JsonFactory.class, Type.class)
|
||||
.newInstance(factory, clazz);
|
||||
Field selfField = newClazz.getDeclaredField("objectEncoderSelf");
|
||||
selfField.setAccessible(true);
|
||||
selfField.set(resultEncoder, selfObjEncoder);
|
||||
(JsonDynEncoder) newClazz.getConstructor(JsonFactory.class, Type.class, ObjectEncoder.class)
|
||||
.newInstance(factory, clazz, selfObjEncoder);
|
||||
if (mixedNames != null) {
|
||||
for (Map.Entry<String, AccessibleObject> en : mixedNames.entrySet()) {
|
||||
Field f = newClazz.getDeclaredField(en.getKey() + "Encoder");
|
||||
@@ -116,8 +117,6 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
||||
supDynName,
|
||||
null);
|
||||
|
||||
fv = cw.visitField(ACC_PROTECTED, "objectEncoderSelf", objEncoderDesc, null, null);
|
||||
fv.visitEnd();
|
||||
final int membersSize = elements.size();
|
||||
boolean onlyTwoIntFieldObjectFlag = false; // 只包含两个int字段
|
||||
boolean onlyOneLatin1FieldObjectFlag = false; // 只包含一个Latin1 String字段
|
||||
@@ -161,12 +160,19 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
||||
onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 字段个数必须大于1
|
||||
}
|
||||
{ // 构造函数
|
||||
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + ")V", null, null));
|
||||
mv = (cw.visitMethod(
|
||||
ACC_PUBLIC, "<init>", "(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null));
|
||||
// mv.setDebug(true);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "(" + jsonfactoryDesc + typeDesc + ")V", false);
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitMethodInsn(
|
||||
INVOKESPECIAL,
|
||||
supDynName,
|
||||
"<init>",
|
||||
"(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V",
|
||||
false);
|
||||
|
||||
for (AccessibleObject element : elements) {
|
||||
final String fieldName = factory.readConvertFieldName(clazz, element);
|
||||
@@ -684,12 +690,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
||||
newClazz, newDynName.replace('/', '.'), JsonFactory.class, Type.class);
|
||||
try {
|
||||
JsonDynEncoder resultEncoder =
|
||||
(JsonDynEncoder) newClazz.getDeclaredConstructor(JsonFactory.class, Type.class)
|
||||
.newInstance(factory, clazz);
|
||||
Field selfField = newClazz.getDeclaredField("objectEncoderSelf");
|
||||
selfField.setAccessible(true);
|
||||
selfField.set(resultEncoder, selfObjEncoder);
|
||||
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), selfField);
|
||||
(JsonDynEncoder) newClazz.getConstructor(JsonFactory.class, Type.class, ObjectEncoder.class)
|
||||
.newInstance(factory, clazz, selfObjEncoder);
|
||||
if (mixedNames != null) {
|
||||
for (Map.Entry<String, AccessibleObject> en : mixedNames.entrySet()) {
|
||||
Field f = newClazz.getDeclaredField(en.getKey() + "Encoder");
|
||||
|
||||
@@ -47,10 +47,11 @@ public class ProtobufArrayEncoder<T> extends ArrayEncoder<ProtobufWriter, T> {
|
||||
} else if (item instanceof CharSequence) {
|
||||
encoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
ProtobufWriter tmp = out.pollChild();
|
||||
encoder.convertTo(tmp, item);
|
||||
out.writeLength(tmp.count());
|
||||
out.writeTo(tmp.toArray());
|
||||
out.offerChild(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +47,11 @@ public class ProtobufCollectionEncoder<T> extends CollectionEncoder<ProtobufWrit
|
||||
} else if (item instanceof CharSequence) {
|
||||
componentEncoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
ProtobufWriter tmp = out.pollChild();
|
||||
componentEncoder.convertTo(tmp, item);
|
||||
out.writeLength(tmp.count());
|
||||
out.writeTo(tmp.toArray());
|
||||
out.offerChild(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
*/
|
||||
package org.redkale.convert.pb;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -17,22 +15,7 @@ import org.redkale.asm.FieldVisitor;
|
||||
import org.redkale.asm.Label;
|
||||
import org.redkale.asm.MethodVisitor;
|
||||
import org.redkale.asm.Opcodes;
|
||||
import static org.redkale.asm.Opcodes.ACC_BRIDGE;
|
||||
import static org.redkale.asm.Opcodes.ACC_FINAL;
|
||||
import static org.redkale.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.redkale.asm.Opcodes.ACC_SUPER;
|
||||
import static org.redkale.asm.Opcodes.ACC_SYNTHETIC;
|
||||
import static org.redkale.asm.Opcodes.ALOAD;
|
||||
import static org.redkale.asm.Opcodes.ASTORE;
|
||||
import static org.redkale.asm.Opcodes.CHECKCAST;
|
||||
import static org.redkale.asm.Opcodes.GETFIELD;
|
||||
import static org.redkale.asm.Opcodes.IFNONNULL;
|
||||
import static org.redkale.asm.Opcodes.INVOKESPECIAL;
|
||||
import static org.redkale.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static org.redkale.asm.Opcodes.POP;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
import static org.redkale.asm.Opcodes.V11;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.util.AnyValue;
|
||||
@@ -59,7 +42,7 @@ public abstract class ProtobufDynEncoder<T> extends ProtobufObjectEncoder<T> {
|
||||
|
||||
// 动态字段: protected EnMember xxxEnMember;
|
||||
|
||||
protected ProtobufDynEncoder(final ProtobufFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
protected ProtobufDynEncoder(ProtobufFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
super((Class) type);
|
||||
this.typeClass = (Class) type;
|
||||
this.factory = factory;
|
||||
@@ -431,13 +414,6 @@ public abstract class ProtobufDynEncoder<T> extends ProtobufObjectEncoder<T> {
|
||||
return generateDyncEncoder(factory, (Class) type);
|
||||
}
|
||||
|
||||
protected static Class readGetSetFieldType(AccessibleObject element) {
|
||||
if (element instanceof Field) {
|
||||
return ((Field) element).getType();
|
||||
}
|
||||
return ((Method) element).getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return typeClass;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ProtobufMapEncoder<K, V> extends MapEncoder<ProtobufWriter, K, V> {
|
||||
|
||||
@Override
|
||||
protected void writeMemberValue(ProtobufWriter out, EnMember member, K key, V value, boolean first) {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
ProtobufWriter tmp = out.pollChild();
|
||||
if (member != null) {
|
||||
out.writeFieldName(member);
|
||||
}
|
||||
@@ -38,5 +38,6 @@ public class ProtobufMapEncoder<K, V> extends MapEncoder<ProtobufWriter, K, V> {
|
||||
valueEncoder.convertTo(tmp, value);
|
||||
out.writeLength(tmp.count());
|
||||
out.writeTo(tmp.toArray());
|
||||
out.offerChild(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,15 @@ public class ProtobufObjectEncoder<T> extends ObjectEncoder<ProtobufWriter, T> {
|
||||
@Override
|
||||
protected ProtobufWriter objectWriter(ProtobufWriter out, T value) {
|
||||
if (out.count() > out.initOffset) {
|
||||
return new ProtobufWriter(out, out.getFeatures()).configFieldFunc(out);
|
||||
return out.pollChild().configParentFunc(out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void offerWriter(ProtobufWriter parent, ProtobufWriter out) {
|
||||
if (parent != out) {
|
||||
parent.offerChild(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +47,11 @@ public class ProtobufStreamEncoder<T> extends StreamEncoder<ProtobufWriter, T> {
|
||||
if (item instanceof CharSequence) {
|
||||
componentEncoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
ProtobufWriter tmp = out.pollChild();
|
||||
componentEncoder.convertTo(tmp, item);
|
||||
out.writeUInt32(tmp.count());
|
||||
out.writeTo(tmp.toArray());
|
||||
out.offerChild(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
"redkale.convert.protobuf.writer.buffer.defsize",
|
||||
Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
||||
|
||||
private static final int CHILD_SIZE = 8;
|
||||
|
||||
private static final int TENTHOUSAND_MAX = 10001;
|
||||
|
||||
private static final byte[][] TENTHOUSAND_UINT_BYTES = new byte[TENTHOUSAND_MAX][];
|
||||
@@ -69,11 +71,13 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
|
||||
protected ProtobufWriter parent;
|
||||
|
||||
protected ProtobufWriter(ProtobufWriter parent, int features) {
|
||||
private ArrayDeque<ProtobufWriter> childWriters;
|
||||
|
||||
protected ProtobufWriter(ProtobufWriter parent) {
|
||||
this();
|
||||
this.parent = parent;
|
||||
this.features = features;
|
||||
if (parent != null) {
|
||||
this.features = parent.features;
|
||||
this.enumtostring = parent.enumtostring;
|
||||
}
|
||||
}
|
||||
@@ -88,6 +92,15 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected ProtobufWriter configParentFunc(ProtobufWriter parent) {
|
||||
this.parent = parent;
|
||||
if (parent != null) {
|
||||
this.features = parent.features;
|
||||
this.enumtostring = parent.enumtostring;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected ProtobufWriter configFieldFunc(ProtobufWriter out) {
|
||||
if (out == null) {
|
||||
return this;
|
||||
@@ -116,6 +129,12 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.parent = null;
|
||||
this.mapFieldFunc = null;
|
||||
this.objFieldFunc = null;
|
||||
this.objExtFunc = null;
|
||||
this.features = 0;
|
||||
this.enumtostring = false;
|
||||
this.count = 0;
|
||||
this.initOffset = 0;
|
||||
if (this.content.length > DEFAULT_SIZE) {
|
||||
@@ -124,6 +143,27 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
return true;
|
||||
}
|
||||
|
||||
public final ProtobufWriter pollChild() {
|
||||
Queue<ProtobufWriter> queue = this.childWriters;
|
||||
if (queue == null) {
|
||||
this.childWriters = new ArrayDeque<>(CHILD_SIZE);
|
||||
queue = this.childWriters;
|
||||
}
|
||||
ProtobufWriter result = queue.poll();
|
||||
if (result == null) {
|
||||
result = new ProtobufWriter();
|
||||
}
|
||||
return result.configFieldFunc(this);
|
||||
}
|
||||
|
||||
public final void offerChild(final ProtobufWriter child) {
|
||||
Queue<ProtobufWriter> queue = this.childWriters;
|
||||
if (child != null && queue != null && queue.size() < CHILD_SIZE) {
|
||||
child.recycle();
|
||||
queue.offer(child);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
return content;
|
||||
@@ -270,7 +310,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
return length;
|
||||
} else {
|
||||
final Class type = obj.getClass();
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
ProtobufWriter tmp = pollChild();
|
||||
if (type == boolean[].class) {
|
||||
for (boolean item : (boolean[]) obj) {
|
||||
tmp.writeBoolean(item);
|
||||
@@ -405,6 +445,7 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
int length = tmp.count();
|
||||
writeLength(length);
|
||||
writeTo(tmp.toArray());
|
||||
offerChild(tmp);
|
||||
return length;
|
||||
}
|
||||
}
|
||||
@@ -1309,11 +1350,12 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
if (arrayEncoder.simple) {
|
||||
if (((Object[]) value).length < 1) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
ProtobufWriter tmp = pollChild();
|
||||
arrayEncoder.convertTo(tmp, member, (Object[]) value);
|
||||
// int length = tmp.count();
|
||||
// this.writeUInt32(length);
|
||||
this.writeTo(tmp.toArray());
|
||||
offerChild(tmp);
|
||||
}
|
||||
} else {
|
||||
arrayEncoder.convertTo(this, member, (Object[]) value);
|
||||
@@ -1323,10 +1365,11 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
if (collectionEncoder.simple) {
|
||||
if (!((Collection) value).isEmpty()) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
ProtobufWriter tmp = pollChild();
|
||||
collectionEncoder.convertTo(tmp, member, (Collection) value);
|
||||
this.writeLength(tmp.count());
|
||||
this.writeTo(tmp.toArray());
|
||||
offerChild(tmp);
|
||||
}
|
||||
} else {
|
||||
collectionEncoder.convertTo(this, member, (Collection) value);
|
||||
@@ -1335,10 +1378,11 @@ public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
ProtobufStreamEncoder streamEncoder = (ProtobufStreamEncoder) encoder;
|
||||
if (streamEncoder.simple) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
ProtobufWriter tmp = pollChild();
|
||||
streamEncoder.convertTo(tmp, member, (Stream) value);
|
||||
this.writeLength(tmp.count());
|
||||
this.writeTo(tmp.toArray());
|
||||
offerChild(tmp);
|
||||
} else {
|
||||
streamEncoder.convertTo(this, member, (Stream) value);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.redkale.test.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.ObjectEncoder;
|
||||
import org.redkale.convert.json.*;
|
||||
|
||||
/** @author zhangjx */
|
||||
@@ -15,8 +16,8 @@ public class _DyncFortuneJsonEncoder extends JsonDynEncoder<Fortune> {
|
||||
|
||||
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
|
||||
|
||||
public _DyncFortuneJsonEncoder(JsonFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
public _DyncFortuneJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
super(factory, type, objectEncoderSelf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +27,7 @@ public class _DyncFortuneJsonEncoder extends JsonDynEncoder<Fortune> {
|
||||
return;
|
||||
}
|
||||
if (!out.isExtFuncEmpty()) {
|
||||
objectEncoder.convertTo(out, value);
|
||||
objectEncoderSelf.convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.redkale.test.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.ObjectEncoder;
|
||||
import org.redkale.convert.json.*;
|
||||
|
||||
/** @author zhangjx */
|
||||
@@ -15,8 +16,8 @@ public class _DyncMessageJsonEncoder extends JsonDynEncoder<Message> {
|
||||
|
||||
protected final byte[] messageCommaFieldBytes = ",\"message\":".getBytes();
|
||||
|
||||
public _DyncMessageJsonEncoder(JsonFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
public _DyncMessageJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
super(factory, type, objectEncoderSelf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +27,7 @@ public class _DyncMessageJsonEncoder extends JsonDynEncoder<Message> {
|
||||
return;
|
||||
}
|
||||
if (!out.isExtFuncEmpty()) {
|
||||
objectEncoder.convertTo(out, value);
|
||||
objectEncoderSelf.convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.redkale.test.convert;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.ObjectEncoder;
|
||||
import org.redkale.convert.json.*;
|
||||
|
||||
/** @author zhangjx */
|
||||
@@ -15,8 +16,8 @@ public class _DyncWorldJsonEncoder extends JsonDynEncoder<World> {
|
||||
|
||||
protected final byte[] randomNumberFieldBytes = ",\"randomNumber\":".getBytes();
|
||||
|
||||
public _DyncWorldJsonEncoder(JsonFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
public _DyncWorldJsonEncoder(JsonFactory factory, Type type, ObjectEncoder objectEncoderSelf) {
|
||||
super(factory, type, objectEncoderSelf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +27,7 @@ public class _DyncWorldJsonEncoder extends JsonDynEncoder<World> {
|
||||
return;
|
||||
}
|
||||
if (!out.isExtFuncEmpty()) {
|
||||
objectEncoder.convertTo(out, value);
|
||||
objectEncoderSelf.convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user