增加ProtobufConvert
This commit is contained in:
@@ -23,17 +23,12 @@ public @interface Scheduled {
|
||||
|
||||
String zone() default "";
|
||||
|
||||
long fixedDelay() default -1;
|
||||
String fixedDelay() default "-1";
|
||||
|
||||
String fixedDelayString() default "";
|
||||
String fixedRate() default "-1";
|
||||
|
||||
long fixedRate() default -1;
|
||||
|
||||
String fixedRateString() default "";
|
||||
|
||||
long initialDelay() default -1;
|
||||
|
||||
String initialDelayString() default "";
|
||||
String initialDelay() default "-1";
|
||||
|
||||
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.redkale.annotation.ConstructorParameters;
|
||||
import org.redkale.convert.bson.BsonConvert;
|
||||
import org.redkale.convert.ext.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.convert.protobuf.ProtobufConvert;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
@@ -36,10 +37,6 @@ import org.redkale.util.*;
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
|
||||
private static final AtomicBoolean loaderInited = new AtomicBoolean();
|
||||
|
||||
private static Convert defProtobufConvert;
|
||||
|
||||
private final ConvertFactory parent;
|
||||
|
||||
protected Convert<R, W> convert;
|
||||
@@ -212,32 +209,27 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
}
|
||||
|
||||
public static Convert findConvert(ConvertType type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
Objects.requireNonNull(type);
|
||||
if (type == ConvertType.JSON) {
|
||||
return JsonConvert.root();
|
||||
}
|
||||
if (type == ConvertType.BSON) {
|
||||
return BsonConvert.root();
|
||||
}
|
||||
if (loaderInited.get()) {
|
||||
if (type == ConvertType.PROTOBUF) {
|
||||
return defProtobufConvert;
|
||||
if (type == ConvertType.PROTOBUF) {
|
||||
return ProtobufConvert.root();
|
||||
}
|
||||
|
||||
Iterator<ConvertProvider> it = ServiceLoader.load(ConvertProvider.class).iterator();
|
||||
RedkaleClassLoader.putServiceLoader(ConvertProvider.class);
|
||||
while (it.hasNext()) {
|
||||
ConvertProvider cl = it.next();
|
||||
RedkaleClassLoader.putReflectionPublicConstructors(cl.getClass(), cl.getClass().getName());
|
||||
if (cl.type() == ConvertType.PROTOBUF) {
|
||||
return cl.convert();
|
||||
}
|
||||
}
|
||||
if (loaderInited.compareAndSet(false, true)) {
|
||||
Iterator<ConvertProvider> it = ServiceLoader.load(ConvertProvider.class).iterator();
|
||||
RedkaleClassLoader.putServiceLoader(ConvertProvider.class);
|
||||
while (it.hasNext()) {
|
||||
ConvertProvider cl = it.next();
|
||||
RedkaleClassLoader.putReflectionPublicConstructors(cl.getClass(), cl.getClass().getName());
|
||||
if (cl.type() == ConvertType.PROTOBUF) {
|
||||
defProtobufConvert = cl.convert();
|
||||
}
|
||||
}
|
||||
}
|
||||
return type == ConvertType.PROTOBUF ? defProtobufConvert : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static int getSystemPropertyInt(String key, String parentkey, boolean defvalue, int feature) {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufArrayDecoder<T> extends ArrayDecoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
private final boolean string;
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufArrayDecoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
|
||||
Type comtype = this.getComponentType();
|
||||
this.string = String.class == comtype;
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
if (simple) return in;
|
||||
return ProtobufFactory.getItemReader(string, simple, in, member, enumtostring, first);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufArrayEncoder<T> extends ArrayEncoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
public ProtobufArrayEncoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
Type comtype = this.getComponentType();
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object item, int index) {
|
||||
if (simple) {
|
||||
if (item == null) {
|
||||
((ProtobufWriter) out).writeUInt32(0);
|
||||
} else {
|
||||
componentEncoder.convertTo(out, item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (member != null) out.writeFieldName(member);
|
||||
if (item == null) {
|
||||
((ProtobufWriter) out).writeUInt32(0);
|
||||
} else if (item instanceof CharSequence) {
|
||||
encoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
encoder.convertTo(tmp, item);
|
||||
int length = tmp.count();
|
||||
((ProtobufWriter) out).writeUInt32(length);
|
||||
((ProtobufWriter) out).writeTo(tmp.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufByteBufferReader extends ProtobufReader {
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int currentIndex = 0;
|
||||
|
||||
private ByteBuffer currentBuffer;
|
||||
|
||||
protected ConvertMask mask;
|
||||
|
||||
protected ProtobufByteBufferReader(ConvertMask mask, ByteBuffer... buffers) {
|
||||
this.mask = mask;
|
||||
this.buffers = buffers;
|
||||
if (buffers != null && buffers.length > 0) this.currentBuffer = buffers[currentIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.currentIndex = 0;
|
||||
this.currentBuffer = null;
|
||||
this.buffers = null;
|
||||
this.mask = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
|
||||
}
|
||||
|
||||
protected byte nextByte() {
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
for (;;) {
|
||||
this.currentBuffer = this.buffers[++this.currentIndex];
|
||||
if (this.currentBuffer.hasRemaining()) {
|
||||
this.position++;
|
||||
return mask == null ? this.currentBuffer.get() : mask.unmask(this.currentBuffer.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// //------------------------------------------------------------
|
||||
// /**
|
||||
// * 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||
// *
|
||||
// * @param startPosition 起始位置
|
||||
// * @param contentLength 内容大小, 不确定的传-1
|
||||
// *
|
||||
// * @return 是否存在
|
||||
// */
|
||||
// @Override
|
||||
// public boolean hasNext(int startPosition, int contentLength) {
|
||||
// //("-------------: " + startPosition + ", " + contentLength + ", " + this.position);
|
||||
// if (startPosition >= 0 && contentLength >= 0) {
|
||||
// return (this.position) < (startPosition + contentLength);
|
||||
// }
|
||||
// return (this.position + 1) < this.content.length;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] readByteArray() {
|
||||
// final int size = readRawVarint32();
|
||||
// byte[] bs = new byte[size];
|
||||
// System.arraycopy(content, position + 1, bs, 0, size);
|
||||
// position += size;
|
||||
// return bs;
|
||||
// }
|
||||
//
|
||||
// protected int readRawVarint32() { //readUInt32
|
||||
// fastpath:
|
||||
// {
|
||||
// int tempPos = this.position;
|
||||
// if ((tempPos + 1) == content.length) break fastpath;
|
||||
//
|
||||
// int x;
|
||||
// if ((x = content[++tempPos]) >= 0) {
|
||||
// this.position = tempPos;
|
||||
// return x;
|
||||
// } else if (content.length - (tempPos + 1) < 9) {
|
||||
// break fastpath;
|
||||
// } else if ((x ^= (content[++tempPos] << 7)) < 0) {
|
||||
// x ^= (~0 << 7);
|
||||
// } else if ((x ^= (content[++tempPos] << 14)) >= 0) {
|
||||
// x ^= (~0 << 7) ^ (~0 << 14);
|
||||
// } else if ((x ^= (content[++tempPos] << 21)) < 0) {
|
||||
// x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
|
||||
// } else {
|
||||
// int y = content[++tempPos];
|
||||
// x ^= y << 28;
|
||||
// x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
|
||||
// if (y < 0
|
||||
// && content[++tempPos] < 0
|
||||
// && content[++tempPos] < 0
|
||||
// && content[++tempPos] < 0
|
||||
// && content[++tempPos] < 0
|
||||
// && content[++tempPos] < 0) {
|
||||
// break fastpath; // Will throw malformedVarint()
|
||||
// }
|
||||
// }
|
||||
// this.position = tempPos;
|
||||
// return x;
|
||||
// }
|
||||
// return (int) readRawVarint64SlowPath();
|
||||
// }
|
||||
//
|
||||
// protected long readRawVarint64() {
|
||||
// fastpath:
|
||||
// {
|
||||
// int tempPos = this.position;
|
||||
// if ((tempPos + 1) == content.length) break fastpath;
|
||||
//
|
||||
// long x;
|
||||
// int y;
|
||||
// if ((y = content[++tempPos]) >= 0) {
|
||||
// this.position = tempPos;
|
||||
// return y;
|
||||
// } else if (content.length - (tempPos + 1) < 9) {
|
||||
// break fastpath;
|
||||
// } else if ((y ^= (content[++tempPos] << 7)) < 0) {
|
||||
// x = y ^ (~0 << 7);
|
||||
// } else if ((y ^= (content[++tempPos] << 14)) >= 0) {
|
||||
// x = y ^ ((~0 << 7) ^ (~0 << 14));
|
||||
// } else if ((y ^= (content[++tempPos] << 21)) < 0) {
|
||||
// x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
|
||||
// } else if ((x = y ^ ((long) content[++tempPos] << 28)) >= 0L) {
|
||||
// x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
|
||||
// } else if ((x ^= ((long) content[++tempPos] << 35)) < 0L) {
|
||||
// x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
|
||||
// } else if ((x ^= ((long) content[++tempPos] << 42)) >= 0L) {
|
||||
// x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
|
||||
// } else if ((x ^= ((long) content[++tempPos] << 49)) < 0L) {
|
||||
// x ^= (~0L << 7)
|
||||
// ^ (~0L << 14)
|
||||
// ^ (~0L << 21)
|
||||
// ^ (~0L << 28)
|
||||
// ^ (~0L << 35)
|
||||
// ^ (~0L << 42)
|
||||
// ^ (~0L << 49);
|
||||
// } else {
|
||||
// x ^= ((long) content[++tempPos] << 56);
|
||||
// x ^= (~0L << 7)
|
||||
// ^ (~0L << 14)
|
||||
// ^ (~0L << 21)
|
||||
// ^ (~0L << 28)
|
||||
// ^ (~0L << 35)
|
||||
// ^ (~0L << 42)
|
||||
// ^ (~0L << 49)
|
||||
// ^ (~0L << 56);
|
||||
// if (x < 0L) {
|
||||
// if (content[++tempPos] < 0L) {
|
||||
// break fastpath; // Will throw malformedVarint()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.position = tempPos;
|
||||
// return x;
|
||||
// }
|
||||
// return readRawVarint64SlowPath();
|
||||
// }
|
||||
//
|
||||
// protected long readRawVarint64SlowPath() {
|
||||
// long result = 0;
|
||||
// for (int shift = 0; shift < 64; shift += 7) {
|
||||
// final byte b = content[++this.position];
|
||||
// result |= (long) (b & 0x7F) << shift;
|
||||
// if ((b & 0x80) == 0) return result;
|
||||
// }
|
||||
// throw new ConvertException("readRawVarint64SlowPath error");
|
||||
// }
|
||||
//
|
||||
// protected int readRawLittleEndian32() {
|
||||
// return ((content[++this.position] & 0xff)
|
||||
// | ((content[++this.position] & 0xff) << 8)
|
||||
// | ((content[++this.position] & 0xff) << 16)
|
||||
// | ((content[++this.position] & 0xff) << 24));
|
||||
// }
|
||||
//
|
||||
// protected long readRawLittleEndian64() {
|
||||
// return ((content[++this.position] & 0xffL)
|
||||
// | ((content[++this.position] & 0xffL) << 8)
|
||||
// | ((content[++this.position] & 0xffL) << 16)
|
||||
// | ((content[++this.position] & 0xffL) << 24)
|
||||
// | ((content[++this.position] & 0xffL) << 32)
|
||||
// | ((content[++this.position] & 0xffL) << 40)
|
||||
// | ((content[++this.position] & 0xffL) << 48)
|
||||
// | ((content[++this.position] & 0xffL) << 56));
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Supplier;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufByteBufferWriter extends ProtobufWriter {
|
||||
|
||||
private final Supplier<ByteBuffer> supplier;
|
||||
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
private int index;
|
||||
|
||||
public ProtobufByteBufferWriter(int features, boolean enumtostring, Supplier<ByteBuffer> supplier) {
|
||||
super((byte[]) null);
|
||||
this.features = features;
|
||||
this.enumtostring = enumtostring;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.buffers = null;
|
||||
this.index = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] toBuffers() {
|
||||
if (buffers == null) {
|
||||
return new ByteBuffer[0];
|
||||
}
|
||||
for (int i = index; i < this.buffers.length; i++) {
|
||||
ByteBuffer buf = this.buffers[i];
|
||||
if (buf.position() != 0) {
|
||||
buf.flip();
|
||||
}
|
||||
}
|
||||
return this.buffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
if (buffers == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
int pos = 0;
|
||||
byte[] bytes = new byte[this.count];
|
||||
for (ByteBuffer buf : toBuffers()) {
|
||||
int r = buf.remaining();
|
||||
buf.get(bytes, pos, r);
|
||||
buf.flip();
|
||||
pos += r;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int expand(final int byteLength) {
|
||||
if (this.buffers == null) {
|
||||
this.index = 0;
|
||||
this.buffers = new ByteBuffer[]{supplier.get()};
|
||||
}
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
if (!buffer.hasRemaining()) {
|
||||
buffer.flip();
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
this.index++;
|
||||
}
|
||||
int len = buffer.remaining();
|
||||
int size = 0;
|
||||
while (len < byteLength) {
|
||||
buffer = supplier.get();
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
len += buffer.remaining();
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
if (expand(len) == 0) {
|
||||
this.buffers[index].put(chs, start, len);
|
||||
} else {
|
||||
ByteBuffer buffer = this.buffers[index];
|
||||
final int end = start + len;
|
||||
int remain = len; //还剩多少没有写
|
||||
while (remain > 0) {
|
||||
final int br = buffer.remaining();
|
||||
if (remain > br) { //一个buffer写不完
|
||||
buffer.put(chs, end - remain, br);
|
||||
buffer = nextByteBuffer();
|
||||
remain -= br;
|
||||
} else {
|
||||
buffer.put(chs, end - remain, remain);
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.count += len;
|
||||
}
|
||||
|
||||
private ByteBuffer nextByteBuffer() {
|
||||
this.buffers[this.index].flip();
|
||||
return this.buffers[++this.index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
this.buffers[index].put(ch);
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");//无需实现
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //无需实现
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufCollectionDecoder<T> extends CollectionDecoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
private final boolean string;
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufCollectionDecoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
|
||||
Type comtype = this.getComponentType();
|
||||
this.string = String.class == comtype;
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
if (simple) return in;
|
||||
return ProtobufFactory.getItemReader(string, simple, in, member, enumtostring, first);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufCollectionEncoder<T> extends CollectionEncoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
|
||||
public ProtobufCollectionEncoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
Type comtype = this.getComponentType();
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object item, boolean first) {
|
||||
if (simple) {
|
||||
if (item == null) {
|
||||
((ProtobufWriter) out).writeUInt32(0);
|
||||
} else {
|
||||
componentEncoder.convertTo(out, item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (member != null) out.writeFieldName(member);
|
||||
if (item == null) {
|
||||
((ProtobufWriter) out).writeUInt32(0);
|
||||
} else if (item instanceof CharSequence) {
|
||||
componentEncoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
componentEncoder.convertTo(tmp, item);
|
||||
int length = tmp.count();
|
||||
((ProtobufWriter) out).writeUInt32(length);
|
||||
((ProtobufWriter) out).writeTo(tmp.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
777
src/main/java/org/redkale/convert/protobuf/ProtobufConvert.java
Normal file
777
src/main/java/org/redkale/convert/protobuf/ProtobufConvert.java
Normal file
@@ -0,0 +1,777 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.ext.StringArraySimpledCoder;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* protobuf的Convert实现 <br>
|
||||
* 注意: <br>
|
||||
* 1、 只实现proto3版本 <br>
|
||||
* 2、 int统一使用sint32, long统一使用sint64 <br>
|
||||
* 3、 集合统一 packed repeated <br>
|
||||
* 4、 目前使用的基础数据类型为:bool、sint32、sint64、float、double、bytes、string、map、Any <br>
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufConvert extends BinaryConvert<ProtobufReader, ProtobufWriter> {
|
||||
|
||||
private final ThreadLocal<ProtobufWriter> writerPool = ThreadLocal.withInitial(ProtobufWriter::new);
|
||||
|
||||
private final Consumer<ProtobufWriter> writerConsumer = w -> offerWriter(w);
|
||||
|
||||
private final ThreadLocal<ProtobufReader> readerPool = ThreadLocal.withInitial(ProtobufReader::new);
|
||||
|
||||
private Encodeable lastConvertEncodeable;
|
||||
|
||||
private Decodeable lastConvertDecodeable;
|
||||
|
||||
protected ProtobufConvert(ConvertFactory<ProtobufReader, ProtobufWriter> factory, int features) {
|
||||
super(factory, features);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory getFactory() {
|
||||
return (ProtobufFactory) factory;
|
||||
}
|
||||
|
||||
public static ProtobufConvert root() {
|
||||
return ProtobufFactory.root().getConvert();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc) {
|
||||
return newConvert(objFieldFunc, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction<Object, Object, Object> mapFieldFunc) {
|
||||
return newConvert(objFieldFunc, mapFieldFunc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
return newConvert(objFieldFunc, null, objExtFunc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||
return new ProtobufConvert(getFactory(), features) {
|
||||
@Override
|
||||
protected <S extends ProtobufWriter> S configWrite(S writer) {
|
||||
super.configWrite(writer);
|
||||
return fieldFunc(writer, fieldFunc, mapFieldFunc, objExtFunc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufReader pollReader() {
|
||||
ProtobufReader reader = readerPool.get();
|
||||
if (reader == null) {
|
||||
reader = new ProtobufReader();
|
||||
} else {
|
||||
readerPool.set(null);
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offerReader(final ProtobufReader in) {
|
||||
if (in != null) {
|
||||
in.recycle();
|
||||
readerPool.set(in);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------ writer -----------------------------------------------------------
|
||||
@Override
|
||||
protected <S extends ProtobufWriter> S configWrite(S writer) {
|
||||
writer.initOffset = writer.count;
|
||||
return writer;
|
||||
}
|
||||
|
||||
public ProtobufByteBufferWriter pollProtobufWriter(final Supplier<ByteBuffer> supplier) {
|
||||
return configWrite(new ProtobufByteBufferWriter(features, ((ProtobufFactory) factory).enumtostring, supplier));
|
||||
}
|
||||
|
||||
public ProtobufWriter pollProtobufWriter(final OutputStream out) {
|
||||
return configWrite(new ProtobufStreamWriter(features, ((ProtobufFactory) factory).enumtostring, out));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufWriter pollWriter() {
|
||||
ProtobufWriter writer = writerPool.get();
|
||||
if (writer == null) {
|
||||
writer = new ProtobufWriter();
|
||||
} else {
|
||||
writerPool.set(null);
|
||||
}
|
||||
return configWrite(writer.withFeatures(features).enumtostring(((ProtobufFactory) factory).enumtostring));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offerWriter(final ProtobufWriter out) {
|
||||
if (out != null) {
|
||||
out.recycle();
|
||||
writerPool.set(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求参数的类型
|
||||
*
|
||||
* @param type 请求参数的类型
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getJsonDecodeDescriptor(Type type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonDecodeDescriptor(null, new ArrayList<>(), type, sb, "", null);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getJsonDecodeDescriptor(Type type, BiFunction<Type, DeMember, Boolean> func) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonDecodeDescriptor(null, new ArrayList<>(), type, sb, "", func);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String getJsonDecodeDescriptor(Type parent, List<String> list, Type type, BiFunction<Type, DeMember, Boolean> func) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonDecodeDescriptor(parent, list, type, sb, "", func);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void defineJsonDecodeDescriptor(Type parent, List<String> list, Type type, StringBuilder sb, String prefix, BiFunction<Type, DeMember, Boolean> excludeFunc) {
|
||||
Decodeable decoder = factory.loadDecoder(type);
|
||||
boolean dot = sb.length() > 0;
|
||||
if (decoder instanceof ObjectDecoder) {
|
||||
if (sb.length() > 0) {
|
||||
if (list.contains(parent + "" + defineTypeName(type))) {
|
||||
return;
|
||||
}
|
||||
list.add(parent + "" + defineTypeName(type));
|
||||
sb.append(prefix).append("\"message ").append(defineTypeName(type)).append("\" : {\r\n");
|
||||
} else {
|
||||
sb.append("{\r\n");
|
||||
}
|
||||
DeMember[] ems = ((ObjectDecoder) decoder).getMembers();
|
||||
List<DeMember> members = new ArrayList<>();
|
||||
for (DeMember member : ems) {
|
||||
if (excludeFunc != null && excludeFunc.apply(type, member)) {
|
||||
continue;
|
||||
}
|
||||
members.add(member);
|
||||
}
|
||||
for (DeMember member : members) {
|
||||
Type mtype = member.getDecoder().getType();
|
||||
if (!(mtype instanceof Class)) {
|
||||
if (mtype instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) mtype;
|
||||
if (pt.getActualTypeArguments().length == 1 && (pt.getActualTypeArguments()[0] instanceof Class)) {
|
||||
defineJsonDecodeDescriptor(parent, list, mtype, sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
} else if (mtype instanceof GenericArrayType) {
|
||||
final GenericArrayType gt = (GenericArrayType) mtype;
|
||||
if (!gt.getGenericComponentType().toString().startsWith("java")
|
||||
&& !gt.getGenericComponentType().toString().startsWith("class java")
|
||||
&& gt.getGenericComponentType().toString().indexOf('.') > 0) {
|
||||
defineJsonDecodeDescriptor(parent, list, gt.getGenericComponentType(), sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Class mclz = (Class) member.getDecoder().getType();
|
||||
if (!mclz.isArray() && !mclz.isEnum() && !mclz.isPrimitive() && !mclz.getName().startsWith("java")) {
|
||||
defineJsonDecodeDescriptor(parent, list, mclz, sb, prefix + " ", excludeFunc);
|
||||
} else if (mclz.isArray() && !mclz.getComponentType().getName().startsWith("java")
|
||||
&& !mclz.getComponentType().isPrimitive() && !mclz.getComponentType().isArray()
|
||||
&& !mclz.getComponentType().getName().equals("boolean") && !mclz.getComponentType().getName().equals("byte")
|
||||
&& !mclz.getComponentType().getName().equals("char") && !mclz.getComponentType().getName().equals("short")
|
||||
&& !mclz.getComponentType().getName().equals("int") && !mclz.getComponentType().getName().equals("long")
|
||||
&& !mclz.getComponentType().getName().equals("float") && !mclz.getComponentType().getName().equals("double")) {
|
||||
defineJsonDecodeDescriptor(parent, list, mclz.getComponentType(), sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
DeMember member = members.get(i);
|
||||
try {
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(member.getDecoder().getType(), ((ProtobufFactory) factory).enumtostring))
|
||||
.append(" ").append(member.getAttribute().field()).append("\" : ").append(member.getPosition()).append(i == members.size() - 1 ? "\r\n" : ",\r\n");
|
||||
} catch (RuntimeException e) {
|
||||
System.err.println("member = " + member);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else if ((!(type instanceof Class) || !((Class) type).isArray() || !((Class) type).getComponentType().getName().startsWith("java")) && (decoder instanceof ProtobufArrayDecoder || decoder instanceof ProtobufCollectionDecoder)) {
|
||||
Type mtype = decoder instanceof ProtobufArrayDecoder ? ((ProtobufArrayDecoder) decoder).getComponentType() : ((ProtobufCollectionDecoder) decoder).getComponentType();
|
||||
if (!mtype.toString().startsWith("java") && !mtype.toString().startsWith("class java") && mtype.toString().indexOf('.') > 0) {
|
||||
defineJsonDecodeDescriptor(parent, list, mtype, sb, prefix, excludeFunc);
|
||||
}
|
||||
} else if (sb.length() == 0) {
|
||||
if (decoder instanceof SimpledCoder
|
||||
|| decoder instanceof StringArraySimpledCoder
|
||||
|| (decoder instanceof ProtobufArrayDecoder && ((ProtobufArrayDecoder) decoder).getComponentDecoder() instanceof SimpledCoder)
|
||||
|| (decoder instanceof ProtobufCollectionDecoder && ((ProtobufCollectionDecoder) decoder).getComponentDecoder() instanceof SimpledCoder)) {
|
||||
sb.append(prefix).append("{\r\n");
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(type, ((ProtobufFactory) factory).enumtostring)).append(" 0\" : 0\r\n");
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else if (decoder instanceof MapDecoder) {
|
||||
sb.append(prefix).append("{\r\n");
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(type, ((ProtobufFactory) factory).enumtostring)).append(" 0\" : 0\r\n");
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else {
|
||||
throw new ConvertException("Not support type (" + type + ")");
|
||||
}
|
||||
} else {
|
||||
throw new ConvertException("Not support the type (" + type + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出结果的类型
|
||||
*
|
||||
* @param type 输出结果的类型
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getJsonEncodeDescriptor(Type type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonEncodeDescriptor(null, new ArrayList<>(), type, sb, "", null);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getJsonEncodeDescriptor(Type type, BiFunction<Type, EnMember, Boolean> func) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonEncodeDescriptor(null, new ArrayList<>(), type, sb, "", func);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String getJsonEncodeDescriptor(Type parent, List<String> list, Type type, BiFunction<Type, EnMember, Boolean> func) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineJsonEncodeDescriptor(parent, list, type, sb, "", func);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void defineJsonEncodeDescriptor(Type parent, List<String> list, Type type, StringBuilder sb, String prefix, BiFunction<Type, EnMember, Boolean> excludeFunc) {
|
||||
Encodeable encoder = factory.loadEncoder(type);
|
||||
boolean dot = sb.length() > 0;
|
||||
if (encoder instanceof ObjectEncoder) {
|
||||
if (sb.length() > 0) {
|
||||
if (list.contains(parent + "" + defineTypeName(type))) {
|
||||
return;
|
||||
}
|
||||
list.add(parent + "" + defineTypeName(type));
|
||||
sb.append(prefix).append("\"message ").append(defineTypeName(type)).append("\" : {\r\n");
|
||||
} else {
|
||||
sb.append("{\r\n");
|
||||
}
|
||||
EnMember[] ems = ((ObjectEncoder) encoder).getMembers();
|
||||
List<EnMember> members = new ArrayList<>();
|
||||
for (EnMember member : ems) {
|
||||
if (excludeFunc != null && excludeFunc.apply(type, member)) {
|
||||
continue;
|
||||
}
|
||||
members.add(member);
|
||||
}
|
||||
for (EnMember member : members) {
|
||||
Type mtype = member.getEncoder().getType();
|
||||
if (!(mtype instanceof Class)) {
|
||||
if (mtype instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) mtype;
|
||||
if (pt.getActualTypeArguments().length == 1 && (pt.getActualTypeArguments()[0] instanceof Class)) {
|
||||
defineJsonEncodeDescriptor(parent, list, mtype, sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
} else if (mtype instanceof GenericArrayType) {
|
||||
final GenericArrayType gt = (GenericArrayType) mtype;
|
||||
if (!gt.getGenericComponentType().toString().startsWith("java")
|
||||
&& !gt.getGenericComponentType().toString().startsWith("class java")
|
||||
&& gt.getGenericComponentType().toString().indexOf('.') > 0) {
|
||||
defineJsonEncodeDescriptor(parent, list, gt.getGenericComponentType(), sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Class mclz = (Class) member.getEncoder().getType();
|
||||
if (!mclz.isArray() && !mclz.isEnum() && !mclz.getName().startsWith("java")) {
|
||||
defineJsonEncodeDescriptor(parent, list, mclz, sb, prefix + " ", excludeFunc);
|
||||
} else if (mclz.isArray() && !mclz.getComponentType().getName().startsWith("java")
|
||||
&& !mclz.getComponentType().getName().equals("boolean") && !mclz.getComponentType().getName().equals("byte")
|
||||
&& !mclz.getComponentType().getName().equals("char") && !mclz.getComponentType().getName().equals("short")
|
||||
&& !mclz.getComponentType().getName().equals("int") && !mclz.getComponentType().getName().equals("long")
|
||||
&& !mclz.getComponentType().getName().equals("float") && !mclz.getComponentType().getName().equals("double")) {
|
||||
defineJsonEncodeDescriptor(parent, list, mclz.getComponentType(), sb, prefix + " ", excludeFunc);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
EnMember member = members.get(i);
|
||||
try {
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(member.getEncoder().getType(), ((ProtobufFactory) factory).enumtostring))
|
||||
.append(" ").append(member.getAttribute().field()).append("\" : ").append(member.getPosition()).append(i == members.size() - 1 ? "\r\n" : ",\r\n");
|
||||
} catch (RuntimeException e) {
|
||||
System.err.println("member = " + member);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else if (encoder instanceof ProtobufArrayEncoder || encoder instanceof ProtobufCollectionEncoder) {
|
||||
Type mtype = encoder instanceof ProtobufArrayEncoder ? ((ProtobufArrayEncoder) encoder).getComponentType() : ((ProtobufCollectionEncoder) encoder).getComponentType();
|
||||
if (!mtype.toString().startsWith("java") && !mtype.toString().startsWith("class java") && mtype.toString().indexOf('.') > 0) {
|
||||
defineJsonEncodeDescriptor(parent, list, mtype, sb, prefix, excludeFunc);
|
||||
}
|
||||
} else if (sb.length() == 0) {
|
||||
if (encoder instanceof SimpledCoder
|
||||
|| (encoder instanceof ProtobufArrayEncoder && ((ProtobufArrayEncoder) encoder).getComponentEncoder() instanceof SimpledCoder)
|
||||
|| (encoder instanceof ProtobufCollectionEncoder && ((ProtobufCollectionEncoder) encoder).getComponentEncoder() instanceof SimpledCoder)) {
|
||||
sb.append(prefix).append("{\r\n");
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(type, ((ProtobufFactory) factory).enumtostring)).append(" 0\" : 0\r\n");
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else if (encoder instanceof MapEncoder) {
|
||||
sb.append(prefix).append("{\r\n");
|
||||
sb.append(prefix).append(" \"").append(ProtobufFactory.wireTypeString(type, ((ProtobufFactory) factory).enumtostring)).append(" 0\" : 0\r\n");
|
||||
sb.append(prefix).append(dot ? "}," : "}").append("\r\n");
|
||||
} else {
|
||||
throw new ConvertException("Not support the type (" + type + ")");
|
||||
}
|
||||
} else {
|
||||
throw new ConvertException("Not support the type (" + type + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public <T> String getProtoDescriptor(Type type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Class clazz = TypeToken.typeToClass(type);
|
||||
sb.append("//java ").append(clazz.isArray() ? (clazz.getComponentType().getName() + "[]") : clazz.getName()).append("\r\n\r\n");
|
||||
if (type instanceof Class) {
|
||||
sb.append("option java_package = \"").append(clazz.getPackage().getName()).append("\";\r\n\r\n");
|
||||
}
|
||||
sb.append("syntax = \"proto3\";\r\n\r\n");
|
||||
//defineProtoDescriptor(type, sb, "");
|
||||
defineProtoDescriptor(null, new ArrayList<>(), type, sb, "", null);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String defineProtoDescriptor(Type parent, List<String> list, Type type, BiFunction<Type, EnMember, Boolean> func) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
defineProtoDescriptor(parent, list, type, sb, "", func);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void defineProtoDescriptor(Type parent, List<String> list, Type type, StringBuilder sb, String prefix, BiFunction<Type, EnMember, Boolean> excludeFunc) {
|
||||
Encodeable encoder = factory.loadEncoder(type);
|
||||
if (encoder instanceof ObjectEncoder) {
|
||||
if (list.contains(parent + "" + defineTypeName(type))) {
|
||||
return;
|
||||
}
|
||||
list.add(parent + "" + defineTypeName(type));
|
||||
|
||||
List<EnMember> members = new ArrayList<>();
|
||||
EnMember[] ems = ((ObjectEncoder) encoder).getMembers();
|
||||
for (EnMember member : ems) {
|
||||
if (excludeFunc != null && excludeFunc.apply(type, member)) {
|
||||
continue;
|
||||
}
|
||||
members.add(member);
|
||||
}
|
||||
final List<StringBuilder> sblist = new ArrayList<>();
|
||||
for (EnMember member : members) {
|
||||
Type mtype = member.getEncoder().getType();
|
||||
if (!(mtype instanceof Class)) {
|
||||
if (mtype instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) mtype;
|
||||
if (pt.getActualTypeArguments().length == 1 && (pt.getActualTypeArguments()[0] instanceof Class)) {
|
||||
StringBuilder innersb = new StringBuilder();
|
||||
defineProtoDescriptor(parent, list, mtype, innersb, prefix, excludeFunc);
|
||||
sblist.add(innersb);
|
||||
}
|
||||
} else if (mtype instanceof GenericArrayType) {
|
||||
final GenericArrayType gt = (GenericArrayType) mtype;
|
||||
if (!gt.getGenericComponentType().toString().startsWith("java")
|
||||
&& !gt.getGenericComponentType().toString().startsWith("class java")
|
||||
&& gt.getGenericComponentType().toString().indexOf('.') > 0) {
|
||||
StringBuilder innersb = new StringBuilder();
|
||||
defineProtoDescriptor(parent, list, gt.getGenericComponentType(), innersb, prefix, excludeFunc);
|
||||
sblist.add(innersb);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Class mclz = (Class) member.getEncoder().getType();
|
||||
if (!mclz.isArray() && !mclz.isEnum() && !mclz.getName().startsWith("java")) {
|
||||
StringBuilder innersb = new StringBuilder();
|
||||
defineProtoDescriptor(parent, list, mclz, innersb, prefix, excludeFunc);
|
||||
sblist.add(innersb);
|
||||
} else if (mclz.isArray() && !mclz.getComponentType().getName().startsWith("java")
|
||||
&& !mclz.getComponentType().getName().equals("boolean") && !mclz.getComponentType().getName().equals("byte")
|
||||
&& !mclz.getComponentType().getName().equals("char") && !mclz.getComponentType().getName().equals("short")
|
||||
&& !mclz.getComponentType().getName().equals("int") && !mclz.getComponentType().getName().equals("long")
|
||||
&& !mclz.getComponentType().getName().equals("float") && !mclz.getComponentType().getName().equals("double")) {
|
||||
StringBuilder innersb = new StringBuilder();
|
||||
defineProtoDescriptor(parent, list, mclz.getComponentType(), innersb, prefix, excludeFunc);
|
||||
sblist.add(innersb);
|
||||
}
|
||||
}
|
||||
for (StringBuilder sbitem : sblist) {
|
||||
if (sbitem.length() < 1) {
|
||||
continue;
|
||||
}
|
||||
sb.append(sbitem.toString().trim()).append("\r\n\r\n");
|
||||
}
|
||||
sb.append(prefix).append("message ").append(defineTypeName(type)).append(" {\r\n");
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
EnMember member = members.get(i);
|
||||
try {
|
||||
sb.append(prefix).append(" ").append(ProtobufFactory.wireTypeString(member.getEncoder().getType(), ((ProtobufFactory) factory).enumtostring))
|
||||
.append(" ").append(member.getAttribute().field()).append(" = ").append(member.getPosition()).append(member.getComment().isEmpty() ? ";\r\n" : ("; //" + member.getComment() + " \r\n"));
|
||||
} catch (RuntimeException e) {
|
||||
System.err.println("member = " + member);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
sb.append(prefix).append("}").append("\r\n");
|
||||
} else if (encoder instanceof ProtobufArrayEncoder || encoder instanceof ProtobufCollectionEncoder) {
|
||||
Type mtype = encoder instanceof ProtobufArrayEncoder ? ((ProtobufArrayEncoder) encoder).getComponentType() : ((ProtobufCollectionEncoder) encoder).getComponentType();
|
||||
if (!mtype.toString().startsWith("java") && !mtype.toString().startsWith("class java") && mtype.toString().indexOf('.') > 0) {
|
||||
defineProtoDescriptor(parent, list, mtype, sb, prefix, excludeFunc);
|
||||
}
|
||||
} else {
|
||||
throw new ConvertException("Not support the type (" + type + ")");
|
||||
}
|
||||
}
|
||||
|
||||
protected StringBuilder defineTypeName(Type type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (type instanceof Class) {
|
||||
sb.append(((Class) type).getSimpleName().replace("[]", "_Array"));
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
Type raw = ((ParameterizedType) type).getRawType();
|
||||
sb.append(((Class) raw).getSimpleName().replace("[]", "_Array"));
|
||||
Type[] ts = ((ParameterizedType) type).getActualTypeArguments();
|
||||
if (ts != null) {
|
||||
for (Type t : ts) {
|
||||
if (t != null) {
|
||||
sb.append('_').append(defineTypeName(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
//------------------------------ convertFrom -----------------------------------------------------------
|
||||
@Override
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
return convertFrom(type, bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int len) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
final ProtobufReader reader = new ProtobufReader(bytes, offset, len);
|
||||
Decodeable decoder = this.lastConvertDecodeable;
|
||||
if (decoder == null || decoder.getType() != type) {
|
||||
decoder = factory.loadDecoder(type);
|
||||
this.lastConvertDecodeable = decoder;
|
||||
}
|
||||
if (!(decoder instanceof ObjectDecoder) && !(decoder instanceof SimpledCoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
T rs = (T) decoder.convertFrom(reader);
|
||||
return rs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final InputStream in) {
|
||||
if (true) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported convertFrom InputStream");
|
||||
}
|
||||
if (type == null || in == null) {
|
||||
return null;
|
||||
}
|
||||
Decodeable decoder = this.lastConvertDecodeable;
|
||||
if (decoder == null || decoder.getType() != type) {
|
||||
decoder = factory.loadDecoder(type);
|
||||
this.lastConvertDecodeable = decoder;
|
||||
}
|
||||
if (!(decoder instanceof ObjectDecoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
return (T) decoder.convertFrom(new ProtobufStreamReader(in));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ByteBuffer... buffers) {
|
||||
if (true) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported convertFrom ByteBuffer");
|
||||
}
|
||||
if (type == null || buffers.length < 1) {
|
||||
return null;
|
||||
}
|
||||
Decodeable decoder = this.lastConvertDecodeable;
|
||||
if (decoder == null || decoder.getType() != type) {
|
||||
decoder = factory.loadDecoder(type);
|
||||
this.lastConvertDecodeable = decoder;
|
||||
}
|
||||
if (!(decoder instanceof ObjectDecoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
return (T) decoder.convertFrom(new ProtobufByteBufferReader((ConvertMask) null, buffers));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers) {
|
||||
if (true) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported convertFrom ByteBuffer");
|
||||
}
|
||||
if (type == null || buffers.length < 1) {
|
||||
return null;
|
||||
}
|
||||
Decodeable decoder = this.lastConvertDecodeable;
|
||||
if (decoder == null || decoder.getType() != type) {
|
||||
decoder = factory.loadDecoder(type);
|
||||
this.lastConvertDecodeable = decoder;
|
||||
}
|
||||
if (!(decoder instanceof ObjectDecoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
return (T) decoder.convertFrom(new ProtobufByteBufferReader(mask, buffers));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertFrom(final Type type, final ProtobufReader reader) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
Decodeable decoder = this.lastConvertDecodeable;
|
||||
if (decoder == null || decoder.getType() != type) {
|
||||
decoder = factory.loadDecoder(type);
|
||||
this.lastConvertDecodeable = decoder;
|
||||
}
|
||||
if (!(decoder instanceof ObjectDecoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
T rs = (T) decoder.convertFrom(reader);
|
||||
return rs;
|
||||
}
|
||||
|
||||
//------------------------------ convertTo -----------------------------------------------------------
|
||||
@Override
|
||||
public byte[] convertTo(final Type type, final Object value) {
|
||||
if (value == null) {
|
||||
final ProtobufWriter writer = pollWriter();
|
||||
writer.writeNull();
|
||||
byte[] result = writer.toArray();
|
||||
offerWriter(writer);
|
||||
return result;
|
||||
}
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
final ProtobufWriter writer = pollWriter();
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder) && !(encoder instanceof SimpledCoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
byte[] result = writer.toArray();
|
||||
offerWriter(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] convertTo(final Object value, int tag, byte... appends) {
|
||||
return convertTo(value.getClass(), value, tag, appends);
|
||||
}
|
||||
|
||||
public byte[] convertTo(final Type type, final Object value, int tag, byte... appends) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
final ProtobufWriter writer = pollWriter();
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != type) {
|
||||
encoder = factory.loadEncoder(type);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(type);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder) && !(encoder instanceof SimpledCoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + type + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
writer.writeUInt32(tag);
|
||||
writer.writeUInt32(appends.length);
|
||||
writer.writeTo(appends);
|
||||
byte[] result = writer.toArray();
|
||||
offerWriter(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertToBytes(final Type type, final Object value) {
|
||||
return convertTo(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler) {
|
||||
final ProtobufWriter writer = pollWriter();
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder) && !(encoder instanceof SimpledCoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
}
|
||||
writer.completed(handler, writerConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||
Objects.requireNonNull(array);
|
||||
final ProtobufWriter writer = configWrite(new ProtobufWriter(array).withFeatures(features).enumtostring(((ProtobufFactory) factory).enumtostring));
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder) && !(encoder instanceof SimpledCoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
}
|
||||
writer.directTo(array);
|
||||
}
|
||||
|
||||
public void convertTo(final OutputStream out, final Type type, final Object value) {
|
||||
if (true) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported convertTo OutputStream");
|
||||
}
|
||||
ProtobufWriter writer = pollProtobufWriter(out);
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
|
||||
//if (true) throw new ConvertException(this.getClass().getSimpleName() + " not supported convertTo ByteBuffer");
|
||||
Objects.requireNonNull(supplier);
|
||||
ProtobufByteBufferWriter writer = pollProtobufWriter(supplier);
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
} else {
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
}
|
||||
return writer.toBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final ProtobufWriter writer, final Type type, final Object value) {
|
||||
if (value == null) {
|
||||
writer.writeNull();
|
||||
return;
|
||||
}
|
||||
writer.initOffset = writer.count;
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
}
|
||||
|
||||
public ProtobufWriter convertToWriter(final Type type, final Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
final ProtobufWriter writer = pollWriter();
|
||||
final Type t = type == null ? value.getClass() : type;
|
||||
Encodeable encoder = this.lastConvertEncodeable;
|
||||
if (encoder == null || encoder.getType() != t) {
|
||||
encoder = factory.loadEncoder(t);
|
||||
this.lastConvertEncodeable = encoder;
|
||||
}
|
||||
if (encoder.specifyable()) {
|
||||
writer.specificObjectType(t);
|
||||
}
|
||||
if (!(encoder instanceof ObjectEncoder)) {
|
||||
throw new ConvertException(this.getClass().getSimpleName() + " not supported type(" + t + ")");
|
||||
}
|
||||
encoder.convertTo(writer, value);
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import org.redkale.annotation.Priority;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Priority(-900)
|
||||
public class ProtobufConvertProvider implements ConvertProvider {
|
||||
|
||||
@Override
|
||||
public ConvertType type() {
|
||||
return ConvertType.PROTOBUF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Convert convert() {
|
||||
return ProtobufConvert.root();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
|
||||
/**
|
||||
* 枚举 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
* @param <E> Enum的子类
|
||||
*/
|
||||
public class ProtobufEnumSimpledCoder<R extends Reader, W extends Writer, E extends Enum> extends SimpledCoder<R, W, E> {
|
||||
|
||||
private final Map<Integer, E> values = new HashMap<>();
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufEnumSimpledCoder(Class<E> type, boolean enumtostring) {
|
||||
this.type = type;
|
||||
this.enumtostring = enumtostring;
|
||||
try {
|
||||
final Method method = type.getMethod("values");
|
||||
RedkaleClassLoader.putReflectionMethod(type.getName(), method);
|
||||
for (E item : (E[]) method.invoke(null)) {
|
||||
values.put(item.ordinal(), item);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertTo(final W out, final E value) {
|
||||
if (value == null) {
|
||||
out.writeNull();
|
||||
} else if (enumtostring) {
|
||||
out.writeSmallString(value.toString());
|
||||
} else {
|
||||
((ProtobufWriter) out).writeUInt32(value.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public E convertFrom(final R in) {
|
||||
if (enumtostring) {
|
||||
String value = in.readSmallString();
|
||||
if (value == null) return null;
|
||||
return (E) Enum.valueOf((Class<E>) type, value);
|
||||
}
|
||||
int value = ((ProtobufReader) in).readRawVarint32();
|
||||
return values.get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<E> getType() {
|
||||
return (Class) type;
|
||||
}
|
||||
|
||||
}
|
||||
340
src/main/java/org/redkale/convert/protobuf/ProtobufFactory.java
Normal file
340
src/main/java/org/redkale/convert/protobuf/ProtobufFactory.java
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.AnyValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufFactory extends ConvertFactory<ProtobufReader, ProtobufWriter> {
|
||||
|
||||
private static final ProtobufFactory instance = new ProtobufFactory(null,
|
||||
getSystemPropertyInt("redkale.convert.protobuf.tiny", "redkale.convert.tiny", true, Convert.FEATURE_TINY)
|
||||
| getSystemPropertyInt("redkale.convert.protobuf.nullable", "redkale.convert.nullable", false, Convert.FEATURE_NULLABLE),
|
||||
Boolean.parseBoolean(System.getProperty("redkale.convert.protobuf.enumtostring", "true")));
|
||||
|
||||
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
||||
|
||||
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
||||
|
||||
protected final boolean enumtostring;
|
||||
|
||||
protected boolean reversible = false;
|
||||
|
||||
static {
|
||||
instance.register(Serializable.class, objectDecoder);
|
||||
instance.register(Serializable.class, objectEncoder);
|
||||
|
||||
instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
|
||||
instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("OverridableMethodCallInConstructor")
|
||||
private ProtobufFactory(ProtobufFactory parent, int features, boolean enumtostring) {
|
||||
super(parent, features);
|
||||
this.enumtostring = enumtostring;
|
||||
if (parent == null) { //root
|
||||
this.register(String[].class, this.createArrayDecoder(String[].class));
|
||||
this.register(String[].class, this.createArrayEncoder(String[].class));
|
||||
}
|
||||
}
|
||||
|
||||
public static ProtobufFactory root() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory withFeatures(int features) {
|
||||
return super.withFeatures(features);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory addFeature(int feature) {
|
||||
return super.addFeature(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory removeFeature(int feature) {
|
||||
return super.removeFeature(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory withTinyFeature(boolean tiny) {
|
||||
return super.withTinyFeature(tiny);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory withNullableFeature(boolean nullable) {
|
||||
return super.withNullableFeature(nullable);
|
||||
}
|
||||
|
||||
public static ProtobufFactory create() {
|
||||
return new ProtobufFactory(null, instance.features, instance.enumtostring);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
|
||||
return new ProtobufEnumSimpledCoder(enumClass, this.enumtostring);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectDecoder createObjectDecoder(Type type) {
|
||||
return new ProtobufObjectDecoder(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectEncoder createObjectEncoder(Type type) {
|
||||
return new ProtobufObjectEncoder(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Decodeable<ProtobufReader, E> createMapDecoder(Type type) {
|
||||
return new ProtobufMapDecoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Encodeable<ProtobufWriter, E> createMapEncoder(Type type) {
|
||||
return new ProtobufMapEncoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Decodeable<ProtobufReader, E> createArrayDecoder(Type type) {
|
||||
return new ProtobufArrayDecoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Encodeable<ProtobufWriter, E> createArrayEncoder(Type type) {
|
||||
return new ProtobufArrayEncoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Decodeable<ProtobufReader, E> createCollectionDecoder(Type type) {
|
||||
return new ProtobufCollectionDecoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Encodeable<ProtobufWriter, E> createCollectionEncoder(Type type) {
|
||||
return new ProtobufCollectionEncoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Decodeable<ProtobufReader, E> createStreamDecoder(Type type) {
|
||||
return new ProtobufStreamDecoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <E> Encodeable<ProtobufWriter, E> createStreamEncoder(Type type) {
|
||||
return new ProtobufStreamEncoder(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ProtobufConvert getConvert() {
|
||||
if (convert == null) {
|
||||
convert = new ProtobufConvert(this, features);
|
||||
}
|
||||
return (ProtobufConvert) convert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory createChild() {
|
||||
return new ProtobufFactory(this, features, this.enumtostring);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufFactory createChild(int features) {
|
||||
return new ProtobufFactory(this, features, this.enumtostring);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConvertType getConvertType() {
|
||||
return ConvertType.PROTOBUF;
|
||||
}
|
||||
|
||||
public ProtobufFactory reversible(boolean reversible) {
|
||||
this.reversible = reversible;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReversible() {
|
||||
return reversible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldSort() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static Reader getItemReader(boolean string, boolean simple, Reader in, DeMember member, boolean enumtostring, boolean first) {
|
||||
if (string) {
|
||||
if (member == null || first) {
|
||||
return in;
|
||||
}
|
||||
ProtobufReader reader = (ProtobufReader) in;
|
||||
int tag = reader.readTag();
|
||||
if (tag != member.getTag()) {
|
||||
reader.backTag(tag);
|
||||
return null;
|
||||
}
|
||||
return in;
|
||||
} else {
|
||||
ProtobufReader reader = (ProtobufReader) in;
|
||||
if (!first && member != null) {
|
||||
int tag = reader.readTag();
|
||||
if (tag != member.getTag()) {
|
||||
reader.backTag(tag);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
byte[] bs = reader.readByteArray();
|
||||
return new ProtobufReader(bs);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTag(String fieldName, Type fieldType, int fieldPos, boolean enumtostring) {
|
||||
int wiretype = ProtobufFactory.wireType(fieldType, enumtostring);
|
||||
return (fieldPos << 3 | wiretype);
|
||||
}
|
||||
|
||||
public static int getTag(DeMember member, boolean enumtostring) {
|
||||
int wiretype = ProtobufFactory.wireType(member.getAttribute().type(), enumtostring);
|
||||
return (member.getPosition() << 3 | wiretype);
|
||||
}
|
||||
|
||||
public static int wireType(Type javaType, boolean enumtostring) {
|
||||
if (javaType == double.class || javaType == Double.class) {
|
||||
return 1;
|
||||
}
|
||||
if (javaType == float.class || javaType == Float.class) {
|
||||
return 5;
|
||||
}
|
||||
if (javaType == boolean.class || javaType == Boolean.class) {
|
||||
return 0;
|
||||
}
|
||||
if (javaType instanceof Class) {
|
||||
Class javaClazz = (Class) javaType;
|
||||
if (javaClazz.isEnum()) {
|
||||
return enumtostring ? 2 : 0;
|
||||
}
|
||||
if (javaClazz.isPrimitive() || Number.class.isAssignableFrom(javaClazz)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
public static String wireTypeString(Type javaType, boolean enumtostring) {
|
||||
if (javaType == double.class || javaType == Double.class) {
|
||||
return "double";
|
||||
}
|
||||
if (javaType == long.class || javaType == Long.class) {
|
||||
return "sint64";
|
||||
}
|
||||
if (javaType == float.class || javaType == Float.class) {
|
||||
return "float";
|
||||
}
|
||||
if (javaType == int.class || javaType == Integer.class) {
|
||||
return "sint32";
|
||||
}
|
||||
if (javaType == short.class || javaType == Short.class) {
|
||||
return "sint32";
|
||||
}
|
||||
if (javaType == char.class || javaType == Character.class) {
|
||||
return "sint32";
|
||||
}
|
||||
if (javaType == byte.class || javaType == Byte.class) {
|
||||
return "sint32";
|
||||
}
|
||||
if (javaType == boolean.class || javaType == Boolean.class) {
|
||||
return "bool";
|
||||
}
|
||||
if (javaType == AtomicLong.class) {
|
||||
return "sint64";
|
||||
}
|
||||
if (javaType == AtomicInteger.class) {
|
||||
return "sint32";
|
||||
}
|
||||
if (javaType == AtomicBoolean.class) {
|
||||
return "bool";
|
||||
}
|
||||
|
||||
if (javaType == double[].class || javaType == Double[].class) {
|
||||
return "repeated double";
|
||||
}
|
||||
if (javaType == long[].class || javaType == Long[].class) {
|
||||
return "repeated sint64";
|
||||
}
|
||||
if (javaType == float[].class || javaType == Float[].class) {
|
||||
return "repeated float";
|
||||
}
|
||||
if (javaType == int[].class || javaType == Integer[].class) {
|
||||
return "repeated sint32";
|
||||
}
|
||||
if (javaType == short[].class || javaType == Short[].class) {
|
||||
return "repeated sint32";
|
||||
}
|
||||
if (javaType == char[].class || javaType == Character[].class) {
|
||||
return "repeated sint32";
|
||||
}
|
||||
if (javaType == byte[].class || javaType == Byte[].class) {
|
||||
return "bytes";
|
||||
}
|
||||
if (javaType == boolean[].class || javaType == Boolean[].class) {
|
||||
return "repeated bool";
|
||||
}
|
||||
if (javaType == AtomicLong[].class) {
|
||||
return "repeated sint64";
|
||||
}
|
||||
if (javaType == AtomicInteger[].class) {
|
||||
return "repeated sint32";
|
||||
}
|
||||
if (javaType == AtomicBoolean[].class) {
|
||||
return "repeated bool";
|
||||
}
|
||||
|
||||
if (javaType == java.util.Properties.class) {
|
||||
return "map<string,string>";
|
||||
}
|
||||
if (javaType instanceof Class) {
|
||||
Class javaClazz = (Class) javaType;
|
||||
if (javaClazz.isArray()) {
|
||||
return "repeated " + wireTypeString(javaClazz.getComponentType(), enumtostring);
|
||||
}
|
||||
if (javaClazz.isEnum()) {
|
||||
return enumtostring ? "string" : javaClazz.getSimpleName();
|
||||
}
|
||||
if (CharSequence.class.isAssignableFrom(javaClazz)) {
|
||||
return "string";
|
||||
}
|
||||
return javaClazz == Object.class ? "Any" : javaClazz.getSimpleName();
|
||||
} else if (javaType instanceof ParameterizedType) { //Collection、Stream、Map 必须是泛型
|
||||
final ParameterizedType pt = (ParameterizedType) javaType;
|
||||
final Class rawType = (Class) pt.getRawType();
|
||||
if (Map.class.isAssignableFrom(rawType)) {
|
||||
Type keyType = pt.getActualTypeArguments()[0];
|
||||
Type valueType = pt.getActualTypeArguments()[1];
|
||||
return "map<" + wireTypeString(keyType, enumtostring) + "," + wireTypeString(valueType, enumtostring) + ">";
|
||||
} else if (Collection.class.isAssignableFrom(rawType)
|
||||
|| Stream.class.isAssignableFrom(rawType) || rawType.isArray()) {
|
||||
return "repeated " + wireTypeString(pt.getActualTypeArguments()[0], enumtostring);
|
||||
} else if (pt.getActualTypeArguments().length == 1
|
||||
&& (pt.getActualTypeArguments()[0] instanceof Class)) {
|
||||
return rawType.getSimpleName() + "_" + ((Class) pt.getActualTypeArguments()[0]).getSimpleName();
|
||||
}
|
||||
} else if (javaType instanceof GenericArrayType) {
|
||||
return "repeated " + wireTypeString(((GenericArrayType) javaType).getGenericComponentType(), enumtostring);
|
||||
}
|
||||
throw new UnsupportedOperationException("ProtobufConvert not supported type(" + javaType + ")");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> K
|
||||
* @param <V> V
|
||||
*/
|
||||
public class ProtobufMapDecoder<K, V> extends MapDecoder<K, V> {
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufMapDecoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader getEntryReader(Reader in, DeMember member, boolean first) {
|
||||
ProtobufReader reader = (ProtobufReader) in;
|
||||
if (!first && member != null) {
|
||||
int tag = reader.readTag();
|
||||
if (tag != member.getTag()) {
|
||||
reader.backTag(tag);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
byte[] bs = reader.readByteArray();
|
||||
return new ProtobufReader(bs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected K readKeyMember(Reader in, DeMember member, Decodeable<Reader, K> decoder, boolean first) {
|
||||
ProtobufReader reader = (ProtobufReader) in;
|
||||
reader.readTag();
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected V readValueMember(Reader in, DeMember member, Decodeable<Reader, V> decoder, boolean first) {
|
||||
ProtobufReader reader = (ProtobufReader) in;
|
||||
reader.readTag();
|
||||
return decoder.convertFrom(in);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> K
|
||||
* @param <V> V
|
||||
*/
|
||||
public class ProtobufMapEncoder<K, V> extends MapEncoder<K, V> {
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufMapEncoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeMemberValue(Writer out, EnMember member, K key, V value, boolean first) {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
if (member != null) out.writeFieldName(member);
|
||||
tmp.writeUInt32(1 << 3 | ProtobufFactory.wireType(keyEncoder.getType(), enumtostring));
|
||||
keyEncoder.convertTo(tmp, key);
|
||||
tmp.writeUInt32(2 << 3 | ProtobufFactory.wireType(valueEncoder.getType(), enumtostring));
|
||||
valueEncoder.convertTo(tmp, value);
|
||||
int length = tmp.count();
|
||||
((ProtobufWriter) out).writeUInt32(length);
|
||||
((ProtobufWriter) out).writeTo(tmp.toArray());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufObjectDecoder<T> extends ObjectDecoder<ProtobufReader, T> {
|
||||
|
||||
protected ProtobufObjectDecoder(Type type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initForEachDeMember(ConvertFactory factory, DeMember member) {
|
||||
Attribute attr = member.getAttribute();
|
||||
setTag(member, ProtobufFactory.getTag(attr.field(), attr.genericType(), member.getPosition(), ((ProtobufFactory) factory).enumtostring));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtobufReader objectReader(ProtobufReader in) {
|
||||
if (in.position() > in.initoffset) return new ProtobufReader(in.readByteArray());
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasNext(ProtobufReader in, boolean first) {
|
||||
return in.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object readDeMemberValue(ProtobufReader in, DeMember member, boolean first) {
|
||||
Decodeable decoder = member.getDecoder();
|
||||
if (decoder instanceof ProtobufArrayDecoder) {
|
||||
return ((ProtobufArrayDecoder) decoder).convertFrom(in, member);
|
||||
} else if (decoder instanceof ProtobufCollectionDecoder) {
|
||||
return ((ProtobufCollectionDecoder) decoder).convertFrom(in, member);
|
||||
} else if (decoder instanceof ProtobufStreamDecoder) {
|
||||
return ((ProtobufStreamDecoder) decoder).convertFrom(in, member);
|
||||
} else if (decoder instanceof ProtobufMapDecoder) {
|
||||
return ((ProtobufMapDecoder) decoder).convertFrom(in, member);
|
||||
} else {
|
||||
return member.read(in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readDeMemberValue(ProtobufReader in, DeMember member, T result, boolean first) {
|
||||
Decodeable decoder = member.getDecoder();
|
||||
if (decoder instanceof ProtobufArrayDecoder) {
|
||||
member.getAttribute().set(result, ((ProtobufArrayDecoder) decoder).convertFrom(in, member));
|
||||
} else if (decoder instanceof ProtobufCollectionDecoder) {
|
||||
member.getAttribute().set(result, ((ProtobufCollectionDecoder) decoder).convertFrom(in, member));
|
||||
} else if (decoder instanceof ProtobufStreamDecoder) {
|
||||
member.getAttribute().set(result, ((ProtobufStreamDecoder) decoder).convertFrom(in, member));
|
||||
} else if (decoder instanceof ProtobufMapDecoder) {
|
||||
member.getAttribute().set(result, ((ProtobufMapDecoder) decoder).convertFrom(in, member));
|
||||
} else {
|
||||
member.read(in, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.Attribute;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufObjectEncoder<T> extends ObjectEncoder<ProtobufWriter, T> {
|
||||
|
||||
protected ProtobufObjectEncoder(Type type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initForEachEnMember(ConvertFactory factory, EnMember member) {
|
||||
Attribute attr = member.getAttribute();
|
||||
setTag(member, ProtobufFactory.getTag(attr.field(), attr.genericType(), member.getPosition(), ((ProtobufFactory) factory).enumtostring));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtobufWriter objectWriter(ProtobufWriter out, T value) {
|
||||
if (out.count() > out.initOffset) {
|
||||
return new ProtobufWriter(out, out.getFeatures()).configFieldFunc(out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
456
src/main/java/org/redkale/convert/protobuf/ProtobufReader.java
Normal file
456
src/main/java/org/redkale/convert/protobuf/ProtobufReader.java
Normal file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.ObjectPool;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufReader extends Reader {
|
||||
|
||||
protected int position = -1;
|
||||
|
||||
protected int initoffset;
|
||||
|
||||
private byte[] content;
|
||||
|
||||
protected int cachetag = Integer.MIN_VALUE;
|
||||
|
||||
protected boolean enumtostring;
|
||||
|
||||
public static ObjectPool<ProtobufReader> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new ProtobufReader(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
public ProtobufReader() {
|
||||
}
|
||||
|
||||
public ProtobufReader(byte[] bytes) {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public ProtobufReader(byte[] bytes, int start, int len) {
|
||||
setBytes(bytes, start, len);
|
||||
}
|
||||
|
||||
public ProtobufReader enumtostring(boolean enumtostring) {
|
||||
this.enumtostring = enumtostring;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(byte[] bytes) {
|
||||
setBytes(bytes);
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
this.initoffset = 0;
|
||||
} else {
|
||||
setBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setBytes(byte[] bytes, int start, int len) {
|
||||
if (bytes == null) {
|
||||
this.position = 0;
|
||||
this.initoffset = 0;
|
||||
} else {
|
||||
this.content = bytes;
|
||||
this.position = start - 1;
|
||||
this.initoffset = this.position;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean recycle() {
|
||||
this.position = -1;
|
||||
this.initoffset = -1;
|
||||
this.content = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public ProtobufReader clear() {
|
||||
this.recycle();
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] remainBytes() {
|
||||
if (this.position >= this.content.length) {
|
||||
return new byte[0];
|
||||
}
|
||||
return Arrays.copyOfRange(this.content, this.position + 1, this.content.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过属性的值
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void skipValue() {
|
||||
int tag = readTag();
|
||||
if (tag == 0) {
|
||||
return;
|
||||
}
|
||||
switch (tag & 0x7) {
|
||||
case 0:
|
||||
readRawVarint32();
|
||||
break;
|
||||
case 1:
|
||||
readRawLittleEndian64();
|
||||
break;
|
||||
case 2:
|
||||
readByteArray();
|
||||
break;
|
||||
case 5:
|
||||
readRawLittleEndian32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readObjectB(final Class clazz) {
|
||||
return (this.position + 1) < this.content.length ? "" : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readObjectE(final Class clazz) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||
return Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readMapE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字符是否为[
|
||||
*
|
||||
* @param member DeMember
|
||||
* @param typevals byte[]
|
||||
* @param componentDecoder Decodeable
|
||||
*
|
||||
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
||||
*/
|
||||
@Override
|
||||
public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
|
||||
if (member == null || componentDecoder == null) {
|
||||
return Reader.SIGN_NOLENBUTBYTES;
|
||||
}
|
||||
Type type = componentDecoder.getType();
|
||||
if (!(type instanceof Class)) {
|
||||
return Reader.SIGN_NOLENBUTBYTES;
|
||||
}
|
||||
Class clazz = (Class) type;
|
||||
if (clazz.isPrimitive() || clazz == Boolean.class || clazz == Byte.class
|
||||
|| clazz == Short.class || clazz == Character.class
|
||||
|| clazz == Integer.class || clazz == Float.class
|
||||
|| clazz == Long.class || clazz == Double.class
|
||||
|| clazz == AtomicInteger.class || clazz == AtomicLong.class) {
|
||||
return Reader.SIGN_NOLENBUTBYTES;
|
||||
}
|
||||
return Reader.SIGN_NOLENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readArrayE() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断下一个非空白字节是否:
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public final void readBlank() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int position() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int readMemberContentLength(DeMember member, Decodeable decoder) {
|
||||
if (member == null && decoder == null) {
|
||||
return -1; //为byte[]
|
||||
}
|
||||
if (member != null) {
|
||||
if (member.getDecoder() instanceof ProtobufArrayDecoder) {
|
||||
ProtobufArrayDecoder pdecoder = (ProtobufArrayDecoder) member.getDecoder();
|
||||
if (pdecoder.simple) {
|
||||
return readRawVarint32();
|
||||
}
|
||||
} else if (member.getDecoder() instanceof ProtobufCollectionDecoder) {
|
||||
ProtobufCollectionDecoder pdecoder = (ProtobufCollectionDecoder) member.getDecoder();
|
||||
if (pdecoder.simple) {
|
||||
return readRawVarint32();
|
||||
}
|
||||
} else if (member.getDecoder() instanceof ProtobufStreamDecoder) {
|
||||
ProtobufStreamDecoder pdecoder = (ProtobufStreamDecoder) member.getDecoder();
|
||||
if (pdecoder.simple) {
|
||||
return readRawVarint32();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return readRawVarint32(); //readUInt32
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DeMember readFieldName(final DeMember[] members, Map<String, DeMember> memberFieldMap, Map<Integer, DeMember> memberTagMap) {
|
||||
int tag = readTag();
|
||||
for (DeMember member : members) {
|
||||
if (member.getTag() == tag) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
backTag(tag);
|
||||
return null;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
@Override
|
||||
public final boolean readBoolean() {
|
||||
return readRawVarint64() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte readByte() {
|
||||
return (byte) readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char readChar() {
|
||||
return (char) readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final short readShort() {
|
||||
return (short) readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int readInt() { //readSInt32
|
||||
int n = readRawVarint32();
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final long readLong() { //readSInt64
|
||||
long n = readRawVarint64();
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final float readFloat() {
|
||||
return Float.intBitsToFloat(readRawLittleEndian32());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double readDouble() {
|
||||
return Double.longBitsToDouble(readRawLittleEndian64());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readClassName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readSmallString() {
|
||||
return readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String readString() {
|
||||
return new String(readByteArray(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
protected final int readTag() {
|
||||
if (cachetag != Integer.MIN_VALUE) {
|
||||
int tag = cachetag;
|
||||
cachetag = Integer.MIN_VALUE;
|
||||
return tag;
|
||||
}
|
||||
return readRawVarint32();
|
||||
}
|
||||
|
||||
protected final void backTag(int tag) {
|
||||
this.cachetag = tag;
|
||||
}
|
||||
|
||||
protected byte currentByte() {
|
||||
return this.content[this.position];
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||
*
|
||||
* @param startPosition 起始位置
|
||||
* @param contentLength 内容大小, 不确定的传-1
|
||||
*
|
||||
* @return 是否存在
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext(int startPosition, int contentLength) {
|
||||
//("-------------: " + startPosition + ", " + contentLength + ", " + this.position);
|
||||
if (startPosition >= 0 && contentLength >= 0) {
|
||||
return (this.position) < (startPosition + contentLength);
|
||||
}
|
||||
return (this.position + 1) < this.content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readByteArray() {
|
||||
final int size = readRawVarint32();
|
||||
byte[] bs = new byte[size];
|
||||
System.arraycopy(content, position + 1, bs, 0, size);
|
||||
position += size;
|
||||
return bs;
|
||||
}
|
||||
|
||||
protected int readRawVarint32() { //readUInt32
|
||||
fastpath:
|
||||
{
|
||||
int tempPos = this.position;
|
||||
if ((tempPos + 1) == content.length) {
|
||||
break fastpath;
|
||||
}
|
||||
|
||||
int x;
|
||||
if ((x = content[++tempPos]) >= 0) {
|
||||
this.position = tempPos;
|
||||
return x;
|
||||
} else if (content.length - (tempPos + 1) < 9) {
|
||||
break fastpath;
|
||||
} else if ((x ^= (content[++tempPos] << 7)) < 0) {
|
||||
x ^= (~0 << 7);
|
||||
} else if ((x ^= (content[++tempPos] << 14)) >= 0) {
|
||||
x ^= (~0 << 7) ^ (~0 << 14);
|
||||
} else if ((x ^= (content[++tempPos] << 21)) < 0) {
|
||||
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
|
||||
} else {
|
||||
int y = content[++tempPos];
|
||||
x ^= y << 28;
|
||||
x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
|
||||
if (y < 0
|
||||
&& content[++tempPos] < 0
|
||||
&& content[++tempPos] < 0
|
||||
&& content[++tempPos] < 0
|
||||
&& content[++tempPos] < 0
|
||||
&& content[++tempPos] < 0) {
|
||||
break fastpath; // Will throw malformedVarint()
|
||||
}
|
||||
}
|
||||
this.position = tempPos;
|
||||
return x;
|
||||
}
|
||||
return (int) readRawVarint64SlowPath();
|
||||
}
|
||||
|
||||
protected long readRawVarint64() {
|
||||
fastpath:
|
||||
{
|
||||
int tempPos = this.position;
|
||||
if ((tempPos + 1) == content.length) {
|
||||
break fastpath;
|
||||
}
|
||||
|
||||
long x;
|
||||
int y;
|
||||
if ((y = content[++tempPos]) >= 0) {
|
||||
this.position = tempPos;
|
||||
return y;
|
||||
} else if (content.length - (tempPos + 1) < 9) {
|
||||
break fastpath;
|
||||
} else if ((y ^= (content[++tempPos] << 7)) < 0) {
|
||||
x = y ^ (~0 << 7);
|
||||
} else if ((y ^= (content[++tempPos] << 14)) >= 0) {
|
||||
x = y ^ ((~0 << 7) ^ (~0 << 14));
|
||||
} else if ((y ^= (content[++tempPos] << 21)) < 0) {
|
||||
x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
|
||||
} else if ((x = y ^ ((long) content[++tempPos] << 28)) >= 0L) {
|
||||
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
|
||||
} else if ((x ^= ((long) content[++tempPos] << 35)) < 0L) {
|
||||
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
|
||||
} else if ((x ^= ((long) content[++tempPos] << 42)) >= 0L) {
|
||||
x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
|
||||
} else if ((x ^= ((long) content[++tempPos] << 49)) < 0L) {
|
||||
x ^= (~0L << 7)
|
||||
^ (~0L << 14)
|
||||
^ (~0L << 21)
|
||||
^ (~0L << 28)
|
||||
^ (~0L << 35)
|
||||
^ (~0L << 42)
|
||||
^ (~0L << 49);
|
||||
} else {
|
||||
x ^= ((long) content[++tempPos] << 56);
|
||||
x ^= (~0L << 7)
|
||||
^ (~0L << 14)
|
||||
^ (~0L << 21)
|
||||
^ (~0L << 28)
|
||||
^ (~0L << 35)
|
||||
^ (~0L << 42)
|
||||
^ (~0L << 49)
|
||||
^ (~0L << 56);
|
||||
if (x < 0L) {
|
||||
if (content[++tempPos] < 0L) {
|
||||
break fastpath; // Will throw malformedVarint()
|
||||
}
|
||||
}
|
||||
}
|
||||
this.position = tempPos;
|
||||
return x;
|
||||
}
|
||||
return readRawVarint64SlowPath();
|
||||
}
|
||||
|
||||
protected long readRawVarint64SlowPath() {
|
||||
long result = 0;
|
||||
for (int shift = 0; shift < 64; shift += 7) {
|
||||
final byte b = content[++this.position];
|
||||
result |= (long) (b & 0x7F) << shift;
|
||||
if ((b & 0x80) == 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new ConvertException("readRawVarint64SlowPath error");
|
||||
}
|
||||
|
||||
protected int readRawLittleEndian32() {
|
||||
return ((content[++this.position] & 0xff)
|
||||
| ((content[++this.position] & 0xff) << 8)
|
||||
| ((content[++this.position] & 0xff) << 16)
|
||||
| ((content[++this.position] & 0xff) << 24));
|
||||
}
|
||||
|
||||
protected long readRawLittleEndian64() {
|
||||
return ((content[++this.position] & 0xffL)
|
||||
| ((content[++this.position] & 0xffL) << 8)
|
||||
| ((content[++this.position] & 0xffL) << 16)
|
||||
| ((content[++this.position] & 0xffL) << 24)
|
||||
| ((content[++this.position] & 0xffL) << 32)
|
||||
| ((content[++this.position] & 0xffL) << 40)
|
||||
| ((content[++this.position] & 0xffL) << 48)
|
||||
| ((content[++this.position] & 0xffL) << 56));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType readType() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 泛型
|
||||
*/
|
||||
public class ProtobufStreamDecoder<T> extends StreamDecoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
private final boolean string;
|
||||
|
||||
private final boolean enumtostring;
|
||||
|
||||
public ProtobufStreamDecoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
this.enumtostring = ((ProtobufFactory) factory).enumtostring;
|
||||
Type comtype = this.getComponentType();
|
||||
this.string = String.class == comtype;
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||
if (simple) return in;
|
||||
return ProtobufFactory.getItemReader(string, simple, in, member, enumtostring, first);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
*/
|
||||
public class ProtobufStreamEncoder<T> extends StreamEncoder<T> {
|
||||
|
||||
protected final boolean simple;
|
||||
|
||||
|
||||
public ProtobufStreamEncoder(ConvertFactory factory, Type type) {
|
||||
super(factory, type);
|
||||
Type comtype = this.getComponentType();
|
||||
this.simple = Boolean.class == comtype || Short.class == comtype
|
||||
|| Character.class == comtype || Integer.class == comtype || Float.class == comtype
|
||||
|| Long.class == comtype || Double.class == comtype
|
||||
|| AtomicInteger.class == comtype || AtomicLong.class == comtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeMemberValue(Writer out, EnMember member, Object item, boolean first) {
|
||||
if (simple) {
|
||||
if (item == null) {
|
||||
((ProtobufWriter) out).writeUInt32(0);
|
||||
} else {
|
||||
componentEncoder.convertTo(out, item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (member != null) out.writeFieldName(member);
|
||||
if (item instanceof CharSequence) {
|
||||
componentEncoder.convertTo(out, item);
|
||||
} else {
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(out);
|
||||
componentEncoder.convertTo(tmp, item);
|
||||
int length = tmp.count();
|
||||
((ProtobufWriter) out).writeUInt32(length);
|
||||
((ProtobufWriter) out).writeTo(tmp.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class ProtobufStreamReader extends ProtobufByteBufferReader {
|
||||
|
||||
private InputStream in;
|
||||
|
||||
private byte currByte;
|
||||
|
||||
protected ProtobufStreamReader(InputStream in) {
|
||||
super((ConvertMask) null);
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle(); // this.position 初始化值为-1
|
||||
this.in = null;
|
||||
this.currByte = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte nextByte() {
|
||||
try {
|
||||
byte b = (currByte = (byte) in.read());
|
||||
this.position++;
|
||||
return b;
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte currentByte() {
|
||||
return currByte;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.io.*;
|
||||
import org.redkale.convert.ConvertException;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class ProtobufStreamWriter extends ProtobufByteBufferWriter {
|
||||
|
||||
private OutputStream out;
|
||||
|
||||
protected ProtobufStreamWriter(int features, boolean enumtostring, OutputStream out) {
|
||||
super(features, enumtostring, null);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.out = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
try {
|
||||
out.write(chs, start, len);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final byte ch) {
|
||||
try {
|
||||
out.write((byte) ch);
|
||||
} catch (IOException e) {
|
||||
throw new ConvertException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
638
src/main/java/org/redkale/convert/protobuf/ProtobufWriter.java
Normal file
638
src/main/java/org/redkale/convert/protobuf/ProtobufWriter.java
Normal file
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.convert.protobuf;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ProtobufWriter extends Writer implements ByteTuple {
|
||||
|
||||
private static final int defaultSize = Integer.getInteger("convert.protobuf.writer.buffer.defsize", Integer.getInteger("convert.writer.buffer.defsize", 1024));
|
||||
|
||||
private byte[] content;
|
||||
|
||||
protected int count;
|
||||
|
||||
protected int initOffset;
|
||||
|
||||
protected boolean enumtostring;
|
||||
|
||||
protected ProtobufWriter parent;
|
||||
|
||||
public static ObjectPool<ProtobufWriter> createPool(int max) {
|
||||
return ObjectPool.createSafePool(max, (Object... params) -> new ProtobufWriter(), null, (t) -> t.recycle());
|
||||
}
|
||||
|
||||
protected ProtobufWriter(ProtobufWriter parent, int features) {
|
||||
this();
|
||||
this.parent = parent;
|
||||
this.features = features;
|
||||
if (parent != null) {
|
||||
this.enumtostring = parent.enumtostring;
|
||||
}
|
||||
}
|
||||
|
||||
protected ProtobufWriter(byte[] bs) {
|
||||
this.content = bs;
|
||||
}
|
||||
|
||||
public ProtobufWriter withFeatures(int features) {
|
||||
super.withFeatures(features);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected ProtobufWriter configFieldFunc(Writer writer) {
|
||||
if (writer == null) {
|
||||
return this;
|
||||
}
|
||||
ProtobufWriter out = (ProtobufWriter) writer;
|
||||
this.mapFieldFunc = out.mapFieldFunc;
|
||||
this.objFieldFunc = out.objFieldFunc;
|
||||
this.objExtFunc = out.objExtFunc;
|
||||
this.features = out.features;
|
||||
this.enumtostring = out.enumtostring;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProtobufWriter() {
|
||||
this(defaultSize);
|
||||
}
|
||||
|
||||
public ProtobufWriter(int size) {
|
||||
this.content = new byte[size > 128 ? size : 128];
|
||||
}
|
||||
|
||||
public ProtobufWriter(ByteArray array) {
|
||||
this.content = array.content();
|
||||
this.count = array.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean recycle() {
|
||||
super.recycle();
|
||||
this.count = 0;
|
||||
this.initOffset = 0;
|
||||
if (this.content.length > defaultSize) {
|
||||
this.content = new byte[defaultSize];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int offset() {
|
||||
return initOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本对象的内容引用复制给array
|
||||
*
|
||||
* @param array ByteArray
|
||||
*/
|
||||
public void directTo(ByteArray array) {
|
||||
array.directFrom(content, count);
|
||||
}
|
||||
|
||||
public ByteBuffer[] toBuffers() {
|
||||
return new ByteBuffer[]{ByteBuffer.wrap(content, 0, count)};
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接获取全部数据, 实际数据需要根据count长度来截取
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public byte[] directBytes() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void completed(ConvertBytesHandler handler, Consumer<ProtobufWriter> callback) {
|
||||
handler.completed(content, 0, count, callback, this);
|
||||
}
|
||||
|
||||
public byte[] toArray() {
|
||||
if (count == content.length) {
|
||||
return content;
|
||||
}
|
||||
byte[] newdata = new byte[count];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
public ProtobufWriter enumtostring(boolean enumtostring) {
|
||||
this.enumtostring = enumtostring;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected int expand(int len) {
|
||||
int newcount = count + len;
|
||||
if (newcount <= content.length) {
|
||||
return 0;
|
||||
}
|
||||
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
|
||||
System.arraycopy(content, 0, newdata, 0, count);
|
||||
this.content = newdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeTo(final byte ch) {
|
||||
expand(1);
|
||||
content[count++] = ch;
|
||||
}
|
||||
|
||||
public final void writeTo(final byte... chs) {
|
||||
writeTo(chs, 0, chs.length);
|
||||
}
|
||||
|
||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
||||
expand(len);
|
||||
System.arraycopy(chs, start, content, count, len);
|
||||
count += len;
|
||||
}
|
||||
|
||||
public ProtobufWriter clear() {
|
||||
this.count = 0;
|
||||
this.initOffset = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
public final int count() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeBoolean(boolean value) {
|
||||
writeTo(value ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNull() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needWriteClassName() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeClassName(String clazz) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeObjectB(Object obj) {
|
||||
super.writeObjectB(obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeObjectE(Object obj) {
|
||||
if (parent != null) {
|
||||
parent.writeUInt32(count());
|
||||
parent.writeTo(toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeArrayB(int size, Encodeable encoder, Encodeable<Writer, Object> componentEncoder, Object obj) {
|
||||
if (obj == null) {
|
||||
writeNull();
|
||||
return 0;
|
||||
} else if (size < 1) {
|
||||
//writeUInt32(0);
|
||||
return 0;
|
||||
} else if (obj instanceof byte[]) {
|
||||
int length = ((byte[]) obj).length;
|
||||
writeUInt32(length);
|
||||
writeTo((byte[]) obj);
|
||||
return length;
|
||||
} else {
|
||||
final Class type = obj.getClass();
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
if (type == boolean[].class) {
|
||||
for (boolean item : (boolean[]) obj) {
|
||||
tmp.writeBoolean(item);
|
||||
}
|
||||
} else if (type == Boolean[].class) {
|
||||
for (Boolean item : (Boolean[]) obj) {
|
||||
tmp.writeBoolean(item == null ? false : item);
|
||||
}
|
||||
} else if (type == short[].class) {
|
||||
for (short item : (short[]) obj) {
|
||||
tmp.writeShort(item);
|
||||
}
|
||||
} else if (type == Short[].class) {
|
||||
for (Short item : (Short[]) obj) {
|
||||
tmp.writeShort(item == null ? 0 : item);
|
||||
}
|
||||
} else if (type == char[].class) {
|
||||
for (char item : (char[]) obj) {
|
||||
tmp.writeChar(item);
|
||||
}
|
||||
} else if (type == Character[].class) {
|
||||
for (Character item : (Character[]) obj) {
|
||||
tmp.writeChar(item == null ? 0 : item);
|
||||
}
|
||||
} else if (type == int[].class) {
|
||||
for (int item : (int[]) obj) {
|
||||
tmp.writeInt(item);
|
||||
}
|
||||
} else if (type == Integer[].class) {
|
||||
for (Integer item : (Integer[]) obj) {
|
||||
tmp.writeInt(item == null ? 0 : item);
|
||||
}
|
||||
} else if (type == float[].class) {
|
||||
for (float item : (float[]) obj) {
|
||||
tmp.writeFloat(item);
|
||||
}
|
||||
} else if (type == Float[].class) {
|
||||
for (Float item : (Float[]) obj) {
|
||||
tmp.writeFloat(item == null ? 0F : item);
|
||||
}
|
||||
} else if (type == long[].class) {
|
||||
for (long item : (long[]) obj) {
|
||||
tmp.writeLong(item);
|
||||
}
|
||||
} else if (type == Long[].class) {
|
||||
for (Long item : (Long[]) obj) {
|
||||
tmp.writeLong(item == null ? 0L : item);
|
||||
}
|
||||
} else if (type == double[].class) {
|
||||
for (double item : (double[]) obj) {
|
||||
tmp.writeDouble(item);
|
||||
}
|
||||
} else if (type == Double[].class) {
|
||||
for (Double item : (Double[]) obj) {
|
||||
tmp.writeDouble(item == null ? 0D : item);
|
||||
}
|
||||
} else if (type == AtomicInteger[].class) {
|
||||
for (AtomicInteger item : (AtomicInteger[]) obj) {
|
||||
tmp.writeInt(item == null ? 0 : item.get());
|
||||
}
|
||||
} else if (type == AtomicLong[].class) {
|
||||
for (AtomicLong item : (AtomicLong[]) obj) {
|
||||
tmp.writeLong(item == null ? 0L : item.get());
|
||||
}
|
||||
} else if (encoder instanceof ProtobufCollectionDecoder) {
|
||||
ProtobufCollectionDecoder listEncoder = (ProtobufCollectionDecoder) encoder;
|
||||
Type componentType = listEncoder.getComponentType();
|
||||
if (listEncoder.simple) {
|
||||
if (componentType == Boolean.class) {
|
||||
for (Boolean item : (Collection<Boolean>) obj) {
|
||||
tmp.writeBoolean(item);
|
||||
}
|
||||
} else if (componentType == Short.class) {
|
||||
for (Short item : (Collection<Short>) obj) {
|
||||
tmp.writeShort(item);
|
||||
}
|
||||
} else if (componentType == Integer.class) {
|
||||
for (Integer item : (Collection<Integer>) obj) {
|
||||
tmp.writeInt(item);
|
||||
}
|
||||
} else if (componentType == Float.class) {
|
||||
for (Float item : (Collection<Float>) obj) {
|
||||
tmp.writeFloat(item);
|
||||
}
|
||||
} else if (componentType == Long.class) {
|
||||
for (Long item : (Collection<Long>) obj) {
|
||||
tmp.writeLong(item);
|
||||
}
|
||||
} else if (componentType == Double.class) {
|
||||
for (Double item : (Collection<Double>) obj) {
|
||||
tmp.writeDouble(item);
|
||||
}
|
||||
} else if (componentType == Long.class) {
|
||||
for (Long item : (Collection<Long>) obj) {
|
||||
tmp.writeLong(item);
|
||||
}
|
||||
} else if (componentType == AtomicInteger.class) {
|
||||
for (AtomicInteger item : (Collection<AtomicInteger>) obj) {
|
||||
tmp.writeInt(item == null ? 0 : item.get());
|
||||
}
|
||||
} else if (componentType == AtomicLong.class) {
|
||||
for (AtomicLong item : (Collection<AtomicLong>) obj) {
|
||||
tmp.writeLong(item == null ? 0L : item.get());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (encoder instanceof ProtobufStreamDecoder) {
|
||||
ProtobufStreamDecoder streamEncoder = (ProtobufStreamDecoder) encoder;
|
||||
Type componentType = streamEncoder.getComponentType();
|
||||
if (streamEncoder.simple) {
|
||||
if (componentType == Boolean.class) {
|
||||
((Stream<Boolean>) obj).forEach(item -> tmp.writeBoolean(item));
|
||||
} else if (componentType == Short.class) {
|
||||
((Stream<Short>) obj).forEach(item -> tmp.writeShort(item));
|
||||
} else if (componentType == Integer.class) {
|
||||
((Stream<Integer>) obj).forEach(item -> tmp.writeInt(item));
|
||||
} else if (componentType == Float.class) {
|
||||
((Stream<Float>) obj).forEach(item -> tmp.writeFloat(item));
|
||||
} else if (componentType == Long.class) {
|
||||
((Stream<Long>) obj).forEach(item -> tmp.writeLong(item));
|
||||
} else if (componentType == Double.class) {
|
||||
((Stream<Double>) obj).forEach(item -> tmp.writeDouble(item));
|
||||
} else if (componentType == AtomicInteger.class) {
|
||||
((Stream<AtomicInteger>) obj).forEach(item -> tmp.writeInt(item == null ? 0 : item.get()));
|
||||
} else if (componentType == AtomicLong.class) {
|
||||
((Stream<AtomicLong>) obj).forEach(item -> tmp.writeLong(item == null ? 0L : item.get()));
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
int length = tmp.count();
|
||||
writeUInt32(length);
|
||||
writeTo(tmp.toArray());
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeArrayMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeArrayE() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMapMark() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMapE() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFieldName(EnMember member, String fieldName, Type fieldType, int fieldPos) {
|
||||
int tag = ProtobufFactory.getTag(fieldName, fieldType, fieldPos, enumtostring);
|
||||
writeUInt32(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeObjectField(final EnMember member, Object obj) {
|
||||
Object value;
|
||||
if (objFieldFunc == null) {
|
||||
value = member.getAttribute().get(obj);
|
||||
} else {
|
||||
value = objFieldFunc.apply(member.getAttribute(), obj);
|
||||
}
|
||||
if (value == null) {
|
||||
this.writeFieldName(member);
|
||||
writeNull();
|
||||
return;
|
||||
}
|
||||
if (tiny()) {
|
||||
if (member.isStringType()) {
|
||||
if (((CharSequence) value).length() == 0) {
|
||||
return;
|
||||
}
|
||||
} else if (member.isBoolType()) {
|
||||
if (!((Boolean) value)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Type mtype = member.getAttribute().type();
|
||||
if (mtype == boolean[].class && ((boolean[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == byte[].class && ((byte[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == short[].class && ((short[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == char[].class && ((char[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == int[].class && ((int[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == float[].class && ((float[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == long[].class && ((long[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
if (mtype == double[].class && ((double[]) value).length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Encodeable encoder = member.getEncoder();
|
||||
if (encoder == null) {
|
||||
return;
|
||||
}
|
||||
if (encoder instanceof MapEncoder) {
|
||||
if (!((Map) value).isEmpty()) {
|
||||
((MapEncoder) encoder).convertTo(this, member, (Map) value);
|
||||
}
|
||||
} else if (encoder instanceof ProtobufArrayEncoder) {
|
||||
ProtobufArrayEncoder arrayEncoder = (ProtobufArrayEncoder) encoder;
|
||||
if (arrayEncoder.simple) {
|
||||
if (((Object[]) value).length < 1) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
arrayEncoder.convertTo(tmp, member, (Object[]) value);
|
||||
//int length = tmp.count();
|
||||
//this.writeUInt32(length);
|
||||
this.writeTo(tmp.toArray());
|
||||
}
|
||||
} else {
|
||||
arrayEncoder.convertTo(this, member, (Object[]) value);
|
||||
}
|
||||
} else if (encoder instanceof ProtobufCollectionEncoder) {
|
||||
ProtobufCollectionEncoder collectionEncoder = (ProtobufCollectionEncoder) encoder;
|
||||
if (collectionEncoder.simple) {
|
||||
if (!((Collection) value).isEmpty()) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
collectionEncoder.convertTo(tmp, member, (Collection) value);
|
||||
int length = tmp.count();
|
||||
this.writeUInt32(length);
|
||||
this.writeTo(tmp.toArray());
|
||||
}
|
||||
} else {
|
||||
collectionEncoder.convertTo(this, member, (Collection) value);
|
||||
}
|
||||
} else if (encoder instanceof ProtobufStreamEncoder) {
|
||||
ProtobufStreamEncoder streamEncoder = (ProtobufStreamEncoder) encoder;
|
||||
if (streamEncoder.simple) {
|
||||
this.writeFieldName(member);
|
||||
ProtobufWriter tmp = new ProtobufWriter().configFieldFunc(this);
|
||||
streamEncoder.convertTo(tmp, member, (Stream) value);
|
||||
int length = tmp.count();
|
||||
this.writeUInt32(length);
|
||||
this.writeTo(tmp.toArray());
|
||||
} else {
|
||||
streamEncoder.convertTo(this, member, (Stream) value);
|
||||
}
|
||||
} else {
|
||||
this.writeFieldName(member);
|
||||
encoder.convertTo(this, value);
|
||||
}
|
||||
this.comma = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(byte value) {
|
||||
writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void writeByteArray(byte[] values) {
|
||||
if (values == null) {
|
||||
writeNull();
|
||||
return;
|
||||
}
|
||||
if (writeArrayB(values.length, null, null, values) < 0) {
|
||||
boolean flag = false;
|
||||
for (byte v : values) {
|
||||
if (flag) {
|
||||
writeArrayMark();
|
||||
}
|
||||
writeByte(v);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
writeArrayE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChar(char value) {
|
||||
writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(short value) {
|
||||
writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int value) { //writeSInt32
|
||||
writeUInt32((value << 1) ^ (value >> 31));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(long value) { //writeSInt64
|
||||
writeUInt64((value << 1) ^ (value >> 63));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloat(float value) {
|
||||
writeFixed32(Float.floatToRawIntBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDouble(double value) {
|
||||
writeFixed64(Double.doubleToRawLongBits(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSmallString(String value) {
|
||||
writeString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeString(String value) {
|
||||
byte[] bs = Utility.isLatin1(value) ? Utility.latin1ByteArray(value) : Utility.encodeUTF8(value);
|
||||
writeUInt32(bs.length);
|
||||
writeTo(bs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeWrapper(StringWrapper value) {
|
||||
if (value != null) {
|
||||
writeString(value.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] uint32(int value) {
|
||||
byte[] bs = new byte[8];
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
if ((value & ~0x7F) == 0) {
|
||||
bs[pos++] = ((byte) value);
|
||||
return pos == bs.length ? bs : Arrays.copyOf(bs, pos);
|
||||
} else {
|
||||
bs[pos++] = ((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeUInt32(int value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7F) == 0) {
|
||||
writeTo((byte) value);
|
||||
return;
|
||||
} else {
|
||||
writeTo((byte) ((value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeUInt64(long value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7FL) == 0) {
|
||||
writeTo((byte) value);
|
||||
return;
|
||||
} else {
|
||||
writeTo((byte) (((int) value & 0x7F) | 0x80));
|
||||
value >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeFixed32(int value) {
|
||||
writeTo((byte) (value & 0xFF), (byte) ((value >> 8) & 0xFF), (byte) ((value >> 16) & 0xFF), (byte) ((value >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
protected void writeFixed64(long value) {
|
||||
writeTo((byte) ((int) (value) & 0xFF),
|
||||
(byte) ((int) (value >> 8) & 0xFF),
|
||||
(byte) ((int) (value >> 16) & 0xFF),
|
||||
(byte) ((int) (value >> 24) & 0xFF),
|
||||
(byte) ((int) (value >> 32) & 0xFF),
|
||||
(byte) ((int) (value >> 40) & 0xFF),
|
||||
(byte) ((int) (value >> 48) & 0xFF),
|
||||
(byte) ((int) (value >> 56) & 0xFF));
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public interface MessageConsumer<T> {
|
||||
default void init(AnyValue config) {
|
||||
}
|
||||
|
||||
public void onMessage(String topic, T[] messages);
|
||||
public void onMessage(String topic, Integer partition, T[] messages);
|
||||
|
||||
default void destroy(AnyValue config) {
|
||||
}
|
||||
|
||||
@@ -19,13 +19,26 @@ import org.redkale.convert.Convert;
|
||||
*/
|
||||
public interface MessageProducer {
|
||||
|
||||
public CompletableFuture<Void> sendMessage(String topic, Object value);
|
||||
public CompletableFuture<Void> sendMessage(String topic, Integer partition, Convert convert, Type type, Object value);
|
||||
|
||||
default CompletableFuture<Void> sendMessage(String topic, Convert convert, Object value) {
|
||||
return sendMessage(topic, convert.convertToBytes(value));
|
||||
default CompletableFuture<Void> sendMessage(String topic, Integer partition, Convert convert, Object value) {
|
||||
return sendMessage(topic, partition, convert, (Type) null, value);
|
||||
}
|
||||
|
||||
default CompletableFuture<Void> sendMessage(String topic, Integer partition, Object value) {
|
||||
return sendMessage(topic, partition, (Convert) null, (Type) null, value);
|
||||
}
|
||||
|
||||
default CompletableFuture<Void> sendMessage(String topic, Convert convert, Type type, Object value) {
|
||||
return sendMessage(topic, convert.convertToBytes(type, value));
|
||||
return sendMessage(topic, (Integer) null, convert, type, value);
|
||||
}
|
||||
|
||||
default CompletableFuture<Void> sendMessage(String topic, Convert convert, Object value) {
|
||||
return sendMessage(topic, (Integer) null, convert, value);
|
||||
}
|
||||
|
||||
default CompletableFuture<Void> sendMessage(String topic, Object value) {
|
||||
return sendMessage(topic, (Integer) null, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.redkale.source;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import org.redkale.convert.ConvertColumn;
|
||||
import static org.redkale.source.ColumnExpress.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
@@ -22,10 +23,13 @@ import org.redkale.util.*;
|
||||
*/
|
||||
public class ColumnValue {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
private String column;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
private ColumnExpress express;
|
||||
|
||||
@ConvertColumn(index = 3)
|
||||
private Serializable value;
|
||||
|
||||
public ColumnValue() {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.test.convert.protobuf;
|
||||
|
||||
import java.util.*;
|
||||
import org.redkale.util.Utility;
|
||||
import org.redkale.convert.protobuf.ProtobufConvert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ArrayBean {
|
||||
|
||||
public static class IntArrayBean {
|
||||
|
||||
public int[] values1;
|
||||
}
|
||||
|
||||
public static class IntListBean {
|
||||
|
||||
public List<Integer> values2;
|
||||
}
|
||||
|
||||
public static class IntegerArrayBean {
|
||||
|
||||
public Integer[] values3;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
IntArrayBean bean1 = new IntArrayBean();
|
||||
bean1.values1 = new int[]{2, 3, 4};
|
||||
IntListBean bean2 = new IntListBean();
|
||||
bean2.values2 = Utility.ofList(2, 3, 4);
|
||||
IntegerArrayBean bean3 = new IntegerArrayBean();
|
||||
bean3.values3 = new Integer[]{2, 3, 4};
|
||||
byte[] bs1 = ProtobufConvert.root().convertTo(bean1);
|
||||
byte[] bs2 = ProtobufConvert.root().convertTo(bean2);
|
||||
byte[] bs3 = ProtobufConvert.root().convertTo(bean3);
|
||||
if (!Arrays.equals(bs1, bs2)) {
|
||||
Utility.println("int数组: ", bs1);
|
||||
Utility.println("int列表: ", bs2);
|
||||
} else if (!Arrays.equals(bs1, bs3)) {
|
||||
Utility.println("int数组: ", bs1);
|
||||
Utility.println("int集合: ", bs3);
|
||||
} else {
|
||||
System.out.println("两者相同");
|
||||
}
|
||||
IntArrayBean bean11 = ProtobufConvert.root().convertFrom(IntArrayBean.class, bs1);
|
||||
IntListBean bean22 = ProtobufConvert.root().convertFrom(IntListBean.class, bs2);
|
||||
IntegerArrayBean bean33 = ProtobufConvert.root().convertFrom(IntegerArrayBean.class, bs3);
|
||||
System.out.println(Arrays.toString(bean11.values1));
|
||||
System.out.println(bean22.values2);
|
||||
System.out.println(Arrays.toString(bean33.values3));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
*/
|
||||
package org.redkale.test.convert.protobuf;
|
||||
|
||||
import org.redkale.convert.protobuf.ProtobufObjectEncoder;
|
||||
import org.redkale.convert.protobuf.ProtobufReader;
|
||||
import org.redkale.convert.protobuf.ProtobufObjectDecoder;
|
||||
import org.redkale.convert.protobuf.ProtobufConvert;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class PBCustMessage2Test {
|
||||
|
||||
private boolean main;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
PBCustMessage2Test test = new PBCustMessage2Test();
|
||||
test.main = true;
|
||||
test.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
final BiFunction<Attribute, Object, Object> objFieldFunc = (Attribute t, Object u) -> {
|
||||
if (t.field().equals("retinfo")) return null;
|
||||
return t.get(u);
|
||||
};
|
||||
OnPlayerLeaveMessage msg1 = new OnPlayerLeaveMessage(100, "haha");
|
||||
byte[] bs1 = ProtobufConvert.root().convertTo(msg1);
|
||||
OnPlayerLeaveMessage2 msg2 = new OnPlayerLeaveMessage2(100, "haha");
|
||||
byte[] bs2 = ProtobufConvert.root().convertTo(msg2);
|
||||
System.out.println(Arrays.toString(bs1));
|
||||
System.out.println(Arrays.toString(bs2));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(bs1), Arrays.toString(bs2));
|
||||
System.out.println();
|
||||
|
||||
OnPlayerLeaveMessage2 newmsg2 = ProtobufConvert.root().convertFrom(OnPlayerLeaveMessage2.class, bs1);
|
||||
byte[] newbs2 = ProtobufConvert.root().convertTo(newmsg2);
|
||||
System.out.println(Arrays.toString(newbs2));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(bs1), Arrays.toString(newbs2));
|
||||
System.out.println();
|
||||
|
||||
ProtobufConvert convert = ProtobufConvert.root().newConvert(objFieldFunc);
|
||||
System.out.println(Arrays.toString(convert.convertTo(msg1)));
|
||||
System.out.println(Arrays.toString(convert.convertTo(msg2)));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(convert.convertTo(msg1)), Arrays.toString(convert.convertTo(msg2)));
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public static interface BaseMessage {
|
||||
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface MessageName {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
public static String getMessageName(Class<?> clazz) {
|
||||
MessageName mn = clazz.getAnnotation(MessageName.class);
|
||||
if (mn != null) return mn.value();
|
||||
char[] fieldChars = clazz.getSimpleName().toCharArray();
|
||||
fieldChars[0] = Character.toLowerCase(fieldChars[0]);
|
||||
return new String(fieldChars);
|
||||
}
|
||||
|
||||
public static Encodeable<Writer, BaseMessage> createConvertEnCoder(final ConvertFactory factory, final Class<? extends BaseMessage> clazz) {
|
||||
Encodeable valEncoder = factory.createEncoder(clazz, true);
|
||||
final String eventName = getMessageName(clazz);
|
||||
ObjectEncoder encoder = new ProtobufObjectEncoder< BaseMessage>(clazz) {
|
||||
@Override
|
||||
protected void afterInitEnMember(ConvertFactory factory) {
|
||||
Function func1 = t -> eventName;
|
||||
Attribute attribute1 = Attribute.create(clazz, "event", String.class, func1, null);
|
||||
EnMember member1 = new EnMember(attribute1, factory.loadEncoder(String.class), null, null);
|
||||
setIndex(member1, 1);
|
||||
setPosition(member1, 1);
|
||||
initForEachEnMember(factory, member1);
|
||||
|
||||
Function func2 = t -> t;
|
||||
Attribute attribute2 = Attribute.create(clazz, "data", clazz, func2, null);
|
||||
EnMember member2 = new EnMember(attribute2, valEncoder, null, null);
|
||||
setIndex(member2, 2);
|
||||
setPosition(member2, 2);
|
||||
initForEachEnMember(factory, member2);
|
||||
this.members = new EnMember[]{member1, member2};
|
||||
}
|
||||
};
|
||||
encoder.init(factory);
|
||||
return encoder;
|
||||
}
|
||||
|
||||
public static Decodeable<Reader, BaseMessage> createConvertDeCoder(final ConvertFactory factory, final Class<? extends BaseMessage> clazz) {
|
||||
Decodeable valDecoder = factory.createDecoder(clazz, true);
|
||||
final String eventName = getMessageName(clazz);
|
||||
ObjectDecoder decoder = new ProtobufObjectDecoder< BaseMessage>(clazz) {
|
||||
@Override
|
||||
protected void afterInitDeMember(ConvertFactory factory) {
|
||||
Function func1 = t -> eventName;
|
||||
Attribute attribute1 = Attribute.create(clazz, "event", String.class, func1, null);
|
||||
DeMember member1 = new DeMember(attribute1, factory.loadDecoder(String.class), null, null);
|
||||
setIndex(member1, 1);
|
||||
setPosition(member1, 1);
|
||||
initForEachDeMember(factory, member1);
|
||||
|
||||
this.creator = (Creator) objs -> new Object[1];
|
||||
Function func2 = t -> t;
|
||||
BiConsumer consumer2 = (t, v) -> ((Object[]) t)[0] = v;
|
||||
Attribute attribute2 = Attribute.create(clazz, "data", clazz, func2, consumer2);
|
||||
DeMember member2 = new DeMember(attribute2, valDecoder, null, null);
|
||||
setIndex(member2, 2);
|
||||
setPosition(member2, 2);
|
||||
initForEachDeMember(factory, member2);
|
||||
this.members = new DeMember[]{member1, member2};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseMessage convertFrom(ProtobufReader in) {
|
||||
Object result = (Object) super.convertFrom(in);
|
||||
return (BaseMessage) ((Object[]) result)[0];
|
||||
}
|
||||
};
|
||||
decoder.init(factory);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@BaseMessage.MessageName("onPlayerLeaveMessage")
|
||||
public static class OnPlayerLeaveMessage2 implements BaseMessage {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
public int userid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
public String retinfo;
|
||||
|
||||
public OnPlayerLeaveMessage2() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage2(int userid, String retinfo) {
|
||||
this.userid = userid;
|
||||
this.retinfo = retinfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnPlayerLeaveMessage {
|
||||
|
||||
private String event = "onPlayerLeaveMessage";
|
||||
|
||||
private OnPlayerLeaveContent result;
|
||||
|
||||
public OnPlayerLeaveMessage() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage(int userid) {
|
||||
this.result = new OnPlayerLeaveContent(userid);
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage(int userid, String retinfo) {
|
||||
this.result = new OnPlayerLeaveContent(userid, retinfo);
|
||||
}
|
||||
|
||||
public String getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public void setEvent(String event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(OnPlayerLeaveContent result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public static class OnPlayerLeaveContent {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
public int userid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
public String retinfo;
|
||||
|
||||
public OnPlayerLeaveContent() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent(int userid) {
|
||||
this.userid = userid;
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent(int userid, String retinfo) {
|
||||
this.userid = userid;
|
||||
this.retinfo = retinfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
*/
|
||||
package org.redkale.test.convert.protobuf;
|
||||
|
||||
import org.redkale.convert.protobuf.ProtobufObjectEncoder;
|
||||
import org.redkale.convert.protobuf.ProtobufReader;
|
||||
import org.redkale.convert.protobuf.ProtobufFactory;
|
||||
import org.redkale.convert.protobuf.ProtobufObjectDecoder;
|
||||
import org.redkale.convert.protobuf.ProtobufConvert;
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.redkale.convert.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class PBCustMessageTest {
|
||||
|
||||
private boolean main;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
PBCustMessageTest test = new PBCustMessageTest();
|
||||
test.main = true;
|
||||
test.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
final BiFunction<Attribute, Object, Object> objFieldFunc = (Attribute t, Object u) -> {
|
||||
if (t.field().equals("retinfo")) return null;
|
||||
return t.get(u);
|
||||
};
|
||||
OnPlayerLeaveMessage msg1 = new OnPlayerLeaveMessage(100, "haha");
|
||||
byte[] bs1 = ProtobufConvert.root().convertTo(msg1);
|
||||
OnPlayerLeaveMessage2 msg2 = new OnPlayerLeaveMessage2(100, "haha");
|
||||
byte[] bs2 = ProtobufConvert.root().convertTo(msg2);
|
||||
System.out.println(Arrays.toString(bs1));
|
||||
System.out.println(Arrays.toString(bs2));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(bs1), Arrays.toString(bs2));
|
||||
System.out.println();
|
||||
|
||||
OnPlayerLeaveMessage2 newmsg2 = ProtobufConvert.root().convertFrom(OnPlayerLeaveMessage2.class, bs1);
|
||||
byte[] newbs2 = ProtobufConvert.root().convertTo(newmsg2);
|
||||
System.out.println(Arrays.toString(newbs2));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(bs1), Arrays.toString(newbs2));
|
||||
System.out.println();
|
||||
|
||||
ProtobufConvert convert = ProtobufConvert.root().newConvert(objFieldFunc);
|
||||
System.out.println(Arrays.toString(convert.convertTo(msg1)));
|
||||
System.out.println(Arrays.toString(convert.convertTo(msg2)));
|
||||
if (!main) Assertions.assertEquals(Arrays.toString(convert.convertTo(msg1)), Arrays.toString(convert.convertTo(msg2)));
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public static interface BaseMessage {
|
||||
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface MessageName {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
public static String getMessageName(Class<?> clazz) {
|
||||
MessageName mn = clazz.getAnnotation(MessageName.class);
|
||||
if (mn != null) return mn.value();
|
||||
char[] fieldChars = clazz.getSimpleName().toCharArray();
|
||||
fieldChars[0] = Character.toLowerCase(fieldChars[0]);
|
||||
return new String(fieldChars);
|
||||
}
|
||||
|
||||
public static Encodeable<Writer, BaseMessage> createConvertCoder(ProtobufFactory factory, Class<?> clazz) {
|
||||
Encodeable valEncoder = factory.createEncoder(clazz, true);
|
||||
ObjectEncoder encoder = new ProtobufObjectEncoder< BaseMessage>(clazz) {
|
||||
@Override
|
||||
protected void afterInitEnMember(ConvertFactory factory) {
|
||||
Function func = t -> t;
|
||||
Attribute attribute = Attribute.create(clazz, getMessageName(clazz), clazz, func, null);
|
||||
EnMember member = new EnMember(attribute, valEncoder, null, null);
|
||||
setIndex(member, 1);
|
||||
setPosition(member, 1);
|
||||
initForEachEnMember(factory, member);
|
||||
this.members = new EnMember[]{member};
|
||||
}
|
||||
};
|
||||
encoder.init(factory);
|
||||
return encoder;
|
||||
}
|
||||
|
||||
public static Decodeable<Reader, BaseMessage> createConvertDeCoder(ProtobufFactory factory, Class<?> clazz) {
|
||||
Decodeable valDecoder = factory.createDecoder(clazz, true);
|
||||
ObjectDecoder decoder = new ProtobufObjectDecoder< BaseMessage>(clazz) {
|
||||
@Override
|
||||
protected void afterInitDeMember(ConvertFactory factory) {
|
||||
this.creator = (Creator) objs -> new Object[1];
|
||||
Function func = t -> t;
|
||||
BiConsumer consumer = (t, v) -> ((Object[]) t)[0] = v;
|
||||
Attribute attribute = Attribute.create(clazz, getMessageName(clazz), clazz, func, consumer);
|
||||
DeMember member = new DeMember(attribute, valDecoder, null, null);
|
||||
setIndex(member, 1);
|
||||
setPosition(member, 1);
|
||||
initForEachDeMember(factory, member);
|
||||
this.members = new DeMember[]{member};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseMessage convertFrom(ProtobufReader in) {
|
||||
Object result = (Object) super.convertFrom(in);
|
||||
return (BaseMessage) ((Object[]) result)[0];
|
||||
}
|
||||
};
|
||||
decoder.init(factory);
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
@BaseMessage.MessageName("onPlayerLeaveMessage")
|
||||
public static class OnPlayerLeaveMessage2 implements BaseMessage {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
public int userid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
public String retinfo;
|
||||
|
||||
public OnPlayerLeaveMessage2() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage2(int userid, String retinfo) {
|
||||
this.userid = userid;
|
||||
this.retinfo = retinfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnPlayerLeaveMessage {
|
||||
|
||||
private OnPlayerLeaveContent onPlayerLeaveMessage;
|
||||
|
||||
public OnPlayerLeaveMessage() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage(int userid) {
|
||||
this.onPlayerLeaveMessage = new OnPlayerLeaveContent(userid);
|
||||
}
|
||||
|
||||
public OnPlayerLeaveMessage(int userid, String retinfo) {
|
||||
this.onPlayerLeaveMessage = new OnPlayerLeaveContent(userid, retinfo);
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent getOnPlayerLeaveMessage() {
|
||||
return onPlayerLeaveMessage;
|
||||
}
|
||||
|
||||
public void setOnPlayerLeaveMessage(OnPlayerLeaveContent onPlayerLeaveMessage) {
|
||||
this.onPlayerLeaveMessage = onPlayerLeaveMessage;
|
||||
}
|
||||
|
||||
public static class OnPlayerLeaveContent {
|
||||
|
||||
@ConvertColumn(index = 1)
|
||||
public int userid;
|
||||
|
||||
@ConvertColumn(index = 2)
|
||||
public String retinfo;
|
||||
|
||||
public OnPlayerLeaveContent() {
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent(int userid) {
|
||||
this.userid = userid;
|
||||
}
|
||||
|
||||
public OnPlayerLeaveContent(int userid, String retinfo) {
|
||||
this.userid = userid;
|
||||
this.retinfo = retinfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// 生成类的包名
|
||||
option java_package = "org.redkalex.test.protobuf";
|
||||
|
||||
message PSimpleBean {
|
||||
|
||||
message PSimpleEntry {
|
||||
sint32 id = 1;
|
||||
string name = 2;
|
||||
string email = 3;
|
||||
}
|
||||
|
||||
message PTwoEntry {
|
||||
sint32 status = 1;
|
||||
sint64 createtime = 2;
|
||||
}
|
||||
PSimpleEntry simple = 1;
|
||||
PTwoEntry two = 2;
|
||||
string strings = 3 ;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// 生成类的包名
|
||||
option java_package = "org.redkalex.test.protobuf";
|
||||
|
||||
message PTestBean {
|
||||
|
||||
message PTestEntry {
|
||||
repeated bool bools = 1;
|
||||
repeated bytes bytes = 2;
|
||||
repeated sint32 chars = 3;
|
||||
repeated sint32 shorts = 4;
|
||||
}
|
||||
|
||||
repeated bool bools = 1;
|
||||
repeated bytes bytes = 2;
|
||||
repeated sint32 chars = 3;
|
||||
repeated PTestEntry entrys = 4;
|
||||
repeated sint32 ints = 5;
|
||||
repeated float floats = 6;
|
||||
repeated sint64 longs = 7;
|
||||
repeated double doubles = 8;
|
||||
repeated string strings = 9;
|
||||
sint32 id = 10;
|
||||
string name = 11;
|
||||
string email = 12;
|
||||
Kind kind = 13;
|
||||
map<string,sint32> map = 14;
|
||||
string end = 15;
|
||||
|
||||
enum Kind {
|
||||
ONE =0;
|
||||
TWO =1;
|
||||
THREE =2;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
105
src/test/java/org/redkale/test/convert/protobuf/SimpleBean.java
Normal file
105
src/test/java/org/redkale/test/convert/protobuf/SimpleBean.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package org.redkale.test.convert.protobuf;
|
||||
|
||||
///*
|
||||
// * To change this license header, choose License Headers in Project Properties.
|
||||
// * To change this template file, choose Tools | Templates
|
||||
// * and open the template in the editor.
|
||||
// */
|
||||
//package org.redkalex.test.protobuf;
|
||||
//
|
||||
//import java.util.Arrays;
|
||||
//import org.redkale.convert.ConvertColumn;
|
||||
//import org.redkale.convert.json.JsonConvert;
|
||||
//import org.redkale.util.Utility;
|
||||
//import org.redkalex.convert.protobuf.ProtobufConvert;
|
||||
//
|
||||
///**
|
||||
// *
|
||||
// * @author zhangjx
|
||||
// */
|
||||
//public class SimpleBean {
|
||||
//
|
||||
// public static class PSimpleEntry {
|
||||
//
|
||||
// @ConvertColumn(index = 1)
|
||||
// public int id = 66;
|
||||
//
|
||||
// @ConvertColumn(index = 2)
|
||||
// public String name = "哈哈";
|
||||
//
|
||||
// @ConvertColumn(index = 3)
|
||||
// public String email = "redkale@redkale.org";
|
||||
// }
|
||||
//
|
||||
// public static class PTwoEntry {
|
||||
//
|
||||
// @ConvertColumn(index = 1)
|
||||
// public int status = 2;
|
||||
//
|
||||
// @ConvertColumn(index = 2)
|
||||
// public long createtime = System.currentTimeMillis();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @ConvertColumn(index = 1)
|
||||
// public PSimpleEntry simple;
|
||||
//
|
||||
// @ConvertColumn(index = 2)
|
||||
// public PTwoEntry two;
|
||||
//
|
||||
// @ConvertColumn(index = 3)
|
||||
// public String strings = "abcd";
|
||||
//
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return JsonConvert.root().convertTo(this);
|
||||
// }
|
||||
//
|
||||
// public static void main(String[] args) throws Throwable {
|
||||
// //System.out.println(ProtobufConvert.root().getProtoDescriptor(SimpleBean.class));
|
||||
// SimpleBean bean = new SimpleBean();
|
||||
// bean.simple = new PSimpleEntry();
|
||||
// bean.two = new PTwoEntry();
|
||||
// bean.strings = "abcde";
|
||||
//
|
||||
// //-------------------------------
|
||||
// byte[] jsonbs = JsonConvert.root().convertToBytes(bean);
|
||||
// byte[] bs = ProtobufConvert.root().convertTo(bean);
|
||||
// Utility.println("predkale ", bs);
|
||||
// PSimpleBeanOuterClass.PSimpleBean.Builder builder = PSimpleBeanOuterClass.PSimpleBean.newBuilder();
|
||||
//
|
||||
// PSimpleBeanOuterClass.PSimpleBean bean2 = createPSimpleBean(bean, builder);
|
||||
// byte[] bs2 = bean2.toByteArray();
|
||||
// Utility.println("protobuf ", bs2);
|
||||
// Thread.sleep(10);
|
||||
// if (!Arrays.equals(bs, bs2)) throw new RuntimeException("两者序列化出来的byte[]不一致");
|
||||
//
|
||||
// System.out.println(bean);
|
||||
// System.out.println(ProtobufConvert.root().convertFrom(SimpleBean.class, bs).toString());
|
||||
// System.out.println(JsonConvert.root().convertFrom(SimpleBean.class, jsonbs).toString());
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static PSimpleBeanOuterClass.PSimpleBean createPSimpleBean(SimpleBean bean, PSimpleBeanOuterClass.PSimpleBean.Builder builder) {
|
||||
// if (builder == null) {
|
||||
// builder = PSimpleBeanOuterClass.PSimpleBean.newBuilder();
|
||||
// } else {
|
||||
// builder.clear();
|
||||
// }
|
||||
// PSimpleBeanOuterClass.PSimpleBean.PSimpleEntry.Builder sentry = PSimpleBeanOuterClass.PSimpleBean.PSimpleEntry.newBuilder();
|
||||
// sentry.setId(bean.simple.id);
|
||||
// sentry.setName(bean.simple.name);
|
||||
// sentry.setEmail(bean.simple.email);
|
||||
// builder.setSimple(sentry.build());
|
||||
//
|
||||
// PSimpleBeanOuterClass.PSimpleBean.PTwoEntry.Builder tentry = PSimpleBeanOuterClass.PSimpleBean.PTwoEntry.newBuilder();
|
||||
// tentry.setStatus(bean.two.status);
|
||||
// tentry.setCreatetime(bean.two.createtime);
|
||||
// builder.setTwo(tentry.build());
|
||||
//
|
||||
// builder.setStrings(bean.strings);
|
||||
//
|
||||
// PSimpleBeanOuterClass.PSimpleBean bean2 = builder.build();
|
||||
// return bean2;
|
||||
// }
|
||||
//}
|
||||
241
src/test/java/org/redkale/test/convert/protobuf/TestBean.java
Normal file
241
src/test/java/org/redkale/test/convert/protobuf/TestBean.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package org.redkale.test.convert.protobuf;
|
||||
|
||||
///*
|
||||
// * To change this license header, choose License Headers in Project Properties.
|
||||
// * To change this template file, choose Tools | Templates
|
||||
// * and open the template in the editor.
|
||||
// */
|
||||
//package org.redkalex.test.protobuf;
|
||||
//
|
||||
//import org.redkalex.convert.protobuf.ProtobufReader;
|
||||
//import org.redkalex.convert.protobuf.ProtobufConvert;
|
||||
//import com.google.protobuf.*;
|
||||
//import java.util.*;
|
||||
//import org.redkale.convert.ConvertColumn;
|
||||
//import org.redkale.convert.json.JsonConvert;
|
||||
//import org.redkale.service.RetResult;
|
||||
//import org.redkale.util.*;
|
||||
//
|
||||
///**
|
||||
// *
|
||||
// * @author zhangjx
|
||||
// */
|
||||
//public class TestBean {
|
||||
//
|
||||
// public static class PTestEntry {
|
||||
//
|
||||
// @ConvertColumn(index = 1)
|
||||
// public boolean[] bools = new boolean[]{true, false, true};
|
||||
//
|
||||
// @ConvertColumn(index = 2)
|
||||
// public byte[] bytes = new byte[]{1, 2, 3, 4};
|
||||
//
|
||||
// @ConvertColumn(index = 3)
|
||||
// public char[] chars = new char[]{'A', 'B', 'C'};
|
||||
//
|
||||
// @ConvertColumn(index = 4)
|
||||
// public short[] shorts = new short[]{10, 20, 30};
|
||||
//
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return JsonConvert.root().convertTo(this);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static enum Kind {
|
||||
// ONE,
|
||||
// TWO,
|
||||
// THREE
|
||||
// }
|
||||
//
|
||||
// @ConvertColumn(index = 1)
|
||||
// public boolean[] bools;
|
||||
//
|
||||
// @ConvertColumn(index = 2)
|
||||
// public byte[] bytes;
|
||||
//
|
||||
// @ConvertColumn(index = 3)
|
||||
// public char[] chars;
|
||||
//
|
||||
// @ConvertColumn(index = 4)
|
||||
// public PTestEntry[] entrys;
|
||||
//
|
||||
// @ConvertColumn(index = 5)
|
||||
// public int[] ints;
|
||||
//
|
||||
// @ConvertColumn(index = 6)
|
||||
// public float[] floats;
|
||||
//
|
||||
// @ConvertColumn(index = 7)
|
||||
// public long[] longs;
|
||||
//
|
||||
// @ConvertColumn(index = 8)
|
||||
// public double[] doubles; //8
|
||||
//
|
||||
// @ConvertColumn(index = 9)
|
||||
// public String[] strings; //9
|
||||
//
|
||||
// @ConvertColumn(index = 10)
|
||||
// public int id = 0x7788; //10
|
||||
//
|
||||
// @ConvertColumn(index = 11)
|
||||
// public String name; //11
|
||||
//
|
||||
// @ConvertColumn(index = 12)
|
||||
// public String email; //12
|
||||
//
|
||||
// @ConvertColumn(index = 13)
|
||||
// public Kind kind; //13
|
||||
//
|
||||
// @ConvertColumn(index = 14)
|
||||
// public Map<String, Integer> map; //14
|
||||
//
|
||||
// @ConvertColumn(index = 15)
|
||||
// public String end; //15
|
||||
//
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return JsonConvert.root().convertTo(this);
|
||||
// }
|
||||
//
|
||||
// public static void main3(String[] args) throws Throwable {
|
||||
// byte[] src = new byte[]{(byte) 0x82, (byte) 0x01, (byte) 0x84, (byte) 0x01, (byte) 0x86, (byte) 0x01};
|
||||
// src = new byte[]{(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01};
|
||||
// CodedInputStream input = CodedInputStream.newInstance(src);
|
||||
// System.out.println("结果1: " + input.readSInt32());
|
||||
// System.out.println("结果1: " + input.readSInt32());
|
||||
// System.out.println("结果1: " + input.readSInt32());
|
||||
// ProtobufReader reader = new ProtobufReader(src);
|
||||
// System.out.println("结果2: " + reader.readInt());
|
||||
// System.out.println("结果2: " + reader.readInt());
|
||||
// System.out.println("结果2: " + reader.readInt());
|
||||
// }
|
||||
//
|
||||
// private static java.lang.reflect.Type retstring = new TypeToken<RetResult<Map<String, String>>>() {
|
||||
// }.getType();
|
||||
//
|
||||
// public static void main2(String[] args) throws Throwable {
|
||||
// System.out.println(ProtobufConvert.root().getProtoDescriptor(retstring));
|
||||
// }
|
||||
//
|
||||
// public static void main(String[] args) throws Throwable {
|
||||
// System.setProperty("convert.protobuf.enumtostring", "false"); //禁用枚举按字符串类型出来
|
||||
// //System.out.println(ProtobufConvert.root().getProtoDescriptor(TestBean.class));
|
||||
// //System.out.println(Integer.toHexString(14<<3|2));
|
||||
// TestBean bean = new TestBean();
|
||||
//
|
||||
// bean.bools = new boolean[]{true, false, true};
|
||||
// bean.bytes = new byte[]{1, 2, 3, 4};
|
||||
// bean.chars = new char[]{'A', 'B', 'C'};
|
||||
// bean.ints = new int[]{100, 200, 300};
|
||||
// bean.floats = new float[]{10.12f, 20.34f};
|
||||
// bean.longs = new long[]{111, 222, 333};
|
||||
// bean.doubles = new double[]{65.65, 78.78};
|
||||
// bean.name = "redkale";
|
||||
// bean.email = "redkale@qq.org";
|
||||
// bean.kind = Kind.TWO;
|
||||
// bean.strings = new String[]{"str1", "str2", "str3"};
|
||||
// bean.entrys = new PTestEntry[]{new PTestEntry(), null, new PTestEntry()};
|
||||
// bean.map = Utility.ofMap("aa", 0x55, "bb", 0x66);
|
||||
// bean.end = "over";
|
||||
//
|
||||
// //-------------------------------
|
||||
// byte[] jsonbs = JsonConvert.root().convertToBytes(bean);
|
||||
// byte[] bs = ProtobufConvert.root().convertTo(bean);
|
||||
// Utility.println("pconvert ", bs);
|
||||
// PTestBeanOuterClass.PTestBean.Builder builder = PTestBeanOuterClass.PTestBean.newBuilder();
|
||||
//
|
||||
// PTestBeanOuterClass.PTestBean bean2 = createPTestBean(bean, builder);
|
||||
// byte[] bs2 = bean2.toByteArray();
|
||||
// Utility.println("protobuf ", bs2);
|
||||
// Thread.sleep(10);
|
||||
// if (!Arrays.equals(bs, bs2)) throw new RuntimeException("两者序列化出来的byte[]不一致");
|
||||
//
|
||||
// System.out.println(bean);
|
||||
// String frombean = ProtobufConvert.root().convertFrom(TestBean.class, bs).toString();
|
||||
// System.out.println(frombean);
|
||||
// if (!bean.toString().equals(frombean)) throw new RuntimeException("ProtobufConvert反解析后的结果不正确");
|
||||
// System.out.println(JsonConvert.root().convertFrom(TestBean.class, jsonbs).toString());
|
||||
//
|
||||
// int count = 100000;
|
||||
// long s, e;
|
||||
// s = System.currentTimeMillis();
|
||||
// for (int z = 0; z < count; z++) {
|
||||
// ProtobufConvert.root().convertTo(bean);
|
||||
// }
|
||||
// e = System.currentTimeMillis() - s;
|
||||
// System.out.println("redkale-protobuf耗时-------" + e);
|
||||
//
|
||||
// s = System.currentTimeMillis();
|
||||
// for (int z = 0; z < count; z++) {
|
||||
// JsonConvert.root().convertToBytes(bean);
|
||||
// }
|
||||
// e = System.currentTimeMillis() - s;
|
||||
// System.out.println("redkale-json文本耗时-------" + e);
|
||||
//
|
||||
// s = System.currentTimeMillis();
|
||||
// for (int z = 0; z < count; z++) {
|
||||
// createPTestBean(bean, builder).toByteArray();
|
||||
// }
|
||||
// e = System.currentTimeMillis() - s;
|
||||
// System.out.println("原生编译protobuf耗时-------" + e);
|
||||
// }
|
||||
//
|
||||
// private static PTestBeanOuterClass.PTestBean createPTestBean(TestBean bean, PTestBeanOuterClass.PTestBean.Builder builder) {
|
||||
// if (builder == null) {
|
||||
// builder = PTestBeanOuterClass.PTestBean.newBuilder();
|
||||
// } else {
|
||||
// builder.clear();
|
||||
// }
|
||||
// for (int i = 0; bean.bools != null && i < bean.bools.length; i++) {
|
||||
// builder.addBools(bean.bools[i]);
|
||||
// }
|
||||
// if (bean.bytes != null) builder.addBytes(ByteString.copyFrom(bean.bytes));
|
||||
// for (int i = 0; bean.chars != null && i < bean.chars.length; i++) {
|
||||
// builder.addChars(bean.chars[i]);
|
||||
// }
|
||||
// for (int i = 0; bean.entrys != null && i < bean.entrys.length; i++) {
|
||||
// PTestBeanOuterClass.PTestBean.PTestEntry.Builder entry = PTestBeanOuterClass.PTestBean.PTestEntry.newBuilder();
|
||||
// if (bean.entrys[i] == null) {
|
||||
// builder.addEntrys(entry.build());
|
||||
// continue;
|
||||
// }
|
||||
// for (int j = 0; bean.entrys[i].bools != null && j < bean.entrys[i].bools.length; j++) {
|
||||
// entry.addBools(bean.entrys[i].bools[j]);
|
||||
// }
|
||||
// if (bean.entrys[i].bytes != null) entry.addBytes(ByteString.copyFrom(bean.entrys[i].bytes));
|
||||
// for (int j = 0; bean.entrys[i].chars != null && j < bean.entrys[i].chars.length; j++) {
|
||||
// entry.addChars(bean.entrys[i].chars[j]);
|
||||
// }
|
||||
// for (int j = 0; bean.entrys[i].shorts != null && j < bean.entrys[i].shorts.length; j++) {
|
||||
// entry.addShorts(bean.entrys[i].shorts[j]);
|
||||
// }
|
||||
// builder.addEntrys(entry.build());
|
||||
// }
|
||||
// for (int i = 0; bean.ints != null && i < bean.ints.length; i++) {
|
||||
// builder.addInts(bean.ints[i]);
|
||||
// }
|
||||
// for (int i = 0; bean.floats != null && i < bean.floats.length; i++) {
|
||||
// builder.addFloats(bean.floats[i]);
|
||||
// }
|
||||
// for (int i = 0; bean.longs != null && i < bean.longs.length; i++) {
|
||||
// builder.addLongs(bean.longs[i]);
|
||||
// }
|
||||
// for (int i = 0; bean.doubles != null && i < bean.doubles.length; i++) {
|
||||
// builder.addDoubles(bean.doubles[i]);
|
||||
// }
|
||||
// for (int i = 0; bean.strings != null && i < bean.strings.length; i++) {
|
||||
// builder.addStrings(bean.strings[i]);
|
||||
// }
|
||||
// builder.setId(bean.id);
|
||||
// if (bean.name != null) builder.setName(bean.name);
|
||||
// if (bean.email != null) builder.setEmail(bean.email);
|
||||
// if (bean.kind != null) builder.setKind(PTestBeanOuterClass.PTestBean.Kind.TWO);
|
||||
// if (bean.map != null) builder.putAllMap(bean.map);
|
||||
// if (bean.end != null) builder.setEnd(bean.end);
|
||||
// PTestBeanOuterClass.PTestBean bean2 = builder.build();
|
||||
// return bean2;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
////protoc --java_out=D:\Java-Projects\RedkalePluginsProject\test\ --proto_path=D:\Java-Projects\RedkalePluginsProject\test\org\redkalex\test\protobuf\ PTestBean.proto
|
||||
Reference in New Issue
Block a user