diff --git a/src/main/java/org/redkale/convert/Convert.java b/src/main/java/org/redkale/convert/Convert.java index f60fb4c51..3ca1d9fb2 100644 --- a/src/main/java/org/redkale/convert/Convert.java +++ b/src/main/java/org/redkale/convert/Convert.java @@ -21,10 +21,14 @@ import org.redkale.util.*; */ public abstract class Convert { - // 值为true时 String类型值为"",Boolean类型值为false时不会输出,默认为false + /** + * 值为true时 (String)"",(Boolean)false值不会输出,默认为false + */ public static final int FEATURE_TINY = 1 << 1; - // 值为true时 字段值为null时会输出,默认为false + /** + * 值为true时 字段值为null时会输出,默认为false + */ public static final int FEATURE_NULLABLE = 1 << 2; // 配置属性集合, 1<<1至1<<10为系统内置 @@ -42,6 +46,7 @@ public abstract class Convert { } protected S configWrite(S writer) { + writer.features = features; return writer; } diff --git a/src/main/java/org/redkale/convert/pb/ProtobufArrayDecoder.java b/src/main/java/org/redkale/convert/pb/ProtobufArrayDecoder.java index f84e9caeb..7fe4c89c0 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufArrayDecoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufArrayDecoder.java @@ -17,35 +17,41 @@ import org.redkale.convert.*; */ public class ProtobufArrayDecoder extends ArrayDecoder implements ProtobufTagDecodeable { + protected final boolean componentPrimitived; protected final boolean componentSimpled; - public ProtobufArrayDecoder(ProtobufFactory factory, Type type) { + public ProtobufArrayDecoder(ConvertFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentDecoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentDecoder() instanceof SimpledCoder; } @Override public T[] convertFrom(ProtobufReader in, DeMember member) { this.checkInited(); - final boolean simpled = this.componentSimpled; + if (componentPrimitived) { + return convertPrimitivedFrom(in, member); + } else if (componentSimpled) { + return convertSimpledFrom(in, member); + } else { + return convertObjectFrom(in, member); + } + } + + protected T[] convertObjectFrom(ProtobufReader in, DeMember member) { final Decodeable itemDecoder = this.componentDecoder; in.readArrayB(itemDecoder); final List result = new ArrayList(); final int limit = in.limit(); while (in.hasNext()) { - boolean nodata = false; - if (!simpled) { - int contentLen = in.readRawVarint32(); - if (contentLen == 0) { - nodata = true; - } else { - in.limit(in.position() + contentLen + 1); - } - } - if (nodata) { + // 读长度 + int contentLen = in.readRawVarint32(); + // 读数据 + if (contentLen == 0) { result.add(null); } else { + in.limit(in.position() + contentLen + 1); result.add(itemDecoder.convertFrom(in)); in.limit(limit); } @@ -54,7 +60,36 @@ public class ProtobufArrayDecoder extends ArrayDecoder } } in.readArrayE(); - T[] rs = this.componentArrayFunction.apply(result.size()); - return result.toArray(rs); + T[] data = this.componentArrayFunction.apply(result.size()); + return result.toArray(data); + } + + protected T[] convertSimpledFrom(ProtobufReader in, DeMember member) { + final Decodeable itemDecoder = this.componentDecoder; + in.readArrayB(itemDecoder); + final List result = new ArrayList(); + while (in.hasNext()) { + // 读数据 + result.add(itemDecoder.convertFrom(in)); + if (!in.readNextTag(member)) { // 元素结束 + break; + } + } + in.readArrayE(); + T[] data = this.componentArrayFunction.apply(result.size()); + return result.toArray(data); + } + + protected T[] convertPrimitivedFrom(ProtobufReader in, DeMember member) { + ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentDecoder; + List result = new ArrayList<>(); + int len = in.readRawVarint32(); + while (len > 0) { + T val = primCoder.convertFrom(in); + len -= primCoder.computeSize(val); + result.add(val); + } + T[] data = this.componentArrayFunction.apply(result.size()); + return result.toArray(data); } } diff --git a/src/main/java/org/redkale/convert/pb/ProtobufArrayEncoder.java b/src/main/java/org/redkale/convert/pb/ProtobufArrayEncoder.java index c9079dc70..a010f7dcc 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufArrayEncoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufArrayEncoder.java @@ -17,21 +17,30 @@ import org.redkale.convert.*; public class ProtobufArrayEncoder extends ArrayEncoder implements ProtobufEncodeable { - protected final boolean componentSimpled; - protected final boolean componentSizeRequired; + protected final boolean componentPrimitived; - public ProtobufArrayEncoder(ProtobufFactory factory, Type type) { + protected final boolean componentSimpled; + + public ProtobufArrayEncoder(ConvertFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentEncoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentEncoder() instanceof SimpledCoder; - this.componentSizeRequired = !(getComponentEncoder() instanceof ProtobufPrimitivable); } @Override public void convertTo(final ProtobufWriter out, @Nonnull EnMember member, T[] value) { this.checkInited(); - if (value == null || value.length < 1) { + if (value == null || value.length == 0) { return; } + if (componentPrimitived) { + convertPrimitivedTo(out, member, value); + } else { + convertObjectTo(out, member, value); + } + } + + protected void convertObjectTo(final ProtobufWriter out, @Nonnull EnMember member, T[] value) { ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; out.writeArrayB(value.length, itemEncoder, value); boolean first = true; @@ -49,25 +58,38 @@ public class ProtobufArrayEncoder extends ArrayEncoder out.writeArrayE(); } + protected void convertPrimitivedTo(final ProtobufWriter out, @Nonnull EnMember member, T[] value) { + out.writeLength(computeSize(out, 0, value)); + Encodeable itemCoder = getComponentEncoder(); + for (T item : value) { + itemCoder.convertTo(out, item); + } + } + @Override public int computeSize(ProtobufWriter out, int tagSize, T[] value) { - if (value == null || value.length < 1) { + if (value == null || value.length == 0) { return 0; } - int dataSize = 0; ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; - for (T item : value) { - dataSize += itemEncoder.computeSize(out, tagSize, item); + if (componentPrimitived) { + int dataSize = 0; + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return dataSize; + } else { + int dataSize = tagSize * value.length; + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return ProtobufFactory.computeSInt32SizeNoTag(dataSize) + dataSize; } - if (componentSizeRequired) { - dataSize += tagSize * value.length; - } - return ProtobufFactory.computeSInt32SizeNoTag(dataSize) + dataSize; } @Override public boolean requireSize() { - return !componentSimpled; + return !componentPrimitived; } @Override diff --git a/src/main/java/org/redkale/convert/pb/ProtobufCoders.java b/src/main/java/org/redkale/convert/pb/ProtobufCoders.java index 27ef2ec60..1d98a6a48 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufCoders.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufCoders.java @@ -11,7 +11,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.*; import java.util.concurrent.atomic.*; -import java.util.function.IntFunction; import java.util.stream.Stream; import org.redkale.convert.SimpledCoder; import org.redkale.convert.ext.AtomicBooleanSimpledCoder; @@ -879,193 +878,6 @@ public abstract class ProtobufCoders { } } - public static class ProtobufPrimitiveArraySimpledCoder extends SimpledCoder - implements ProtobufEncodeable { - - private final IntFunction arrayFunc; - private final SimpledCoder componentCoder; - - public ProtobufPrimitiveArraySimpledCoder(ProtobufPrimitivable primitiveCoder) { - this.componentCoder = (SimpledCoder) primitiveCoder; - this.arrayFunc = Creator.funcArray(TypeToken.typeToClass(this.componentCoder.getType())); - } - - @Override - public void convertTo(ProtobufWriter out, T[] value) { - if (value == null || value.length == 0) { - return; - } - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - T[] array = value; - int len = 0; - for (T item : array) { - len += primCoder.computeSize(item == null ? 0 : item); - } - out.writeLength(len); - for (T item : array) { - itemCoder.convertTo(out, item); - } - } - - @Override - public T[] convertFrom(ProtobufReader in) { - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - List data = new ArrayList<>(); - int len = in.readRawVarint32(); - while (len > 0) { - T val = itemCoder.convertFrom(in); - len -= primCoder.computeSize(val); - data.add(val); - } - return data.toArray(this.arrayFunc); - } - - @Override - public int computeSize(ProtobufWriter out, int tagSize, T[] value) { - if (value == null || value.length == 0) { - return 0; - } - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentCoder; - int len = 0; - for (T item : value) { - len += primCoder.computeSize(item); - } - return len; - } - - @Override - public final ProtobufTypeEnum typeEnum() { - return ProtobufTypeEnum.BYTES; - } - } - - public static class ProtobufPrimitiveCollectionSimpledCoder - extends SimpledCoder> - implements ProtobufEncodeable> { - - private final Creator creator; - - private final SimpledCoder componentCoder; - - public ProtobufPrimitiveCollectionSimpledCoder( - Creator creator, ProtobufPrimitivable primitiveCoder) { - this.creator = creator; - this.componentCoder = (SimpledCoder) primitiveCoder; - } - - @Override - public void convertTo(ProtobufWriter out, Collection values) { - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - Collection array = values; - if (array != null && !array.isEmpty()) { - int len = 0; - for (T item : array) { - len += primCoder.computeSize(item == null ? 0 : item); - } - out.writeLength(len); - for (T item : array) { - itemCoder.convertTo(out, item); - } - } - } - - @Override - public Collection convertFrom(ProtobufReader in) { - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - Collection data = creator.create(); - int len = in.readRawVarint32(); - while (len > 0) { - T val = itemCoder.convertFrom(in); - len -= primCoder.computeSize(val); - data.add(val); - } - return data; - } - - @Override - public int computeSize(ProtobufWriter out, int tagSize, Collection value) { - if (value == null || value.isEmpty()) { - return 0; - } - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentCoder; - int len = 0; - for (T item : value) { - len += primCoder.computeSize(item); - } - return len; - } - - @Override - public final ProtobufTypeEnum typeEnum() { - return ProtobufTypeEnum.BYTES; - } - } - - public static class ProtobufPrimitiveStreamSimpledCoder - extends SimpledCoder> - implements ProtobufEncodeable> { - - private final SimpledCoder componentCoder; - - public ProtobufPrimitiveStreamSimpledCoder(ProtobufPrimitivable primitiveCoder) { - this.componentCoder = (SimpledCoder) primitiveCoder; - } - - @Override - public void convertTo(ProtobufWriter out, Stream value) { - if (value == null) { - return; - } - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - Object[] array = value.toArray(); - int len = 0; - for (Object item : array) { - len += primCoder.computeSize(item == null ? 0 : item); - } - out.writeLength(len); - for (Object item : array) { - itemCoder.convertTo(out, (T) item); - } - } - - @Override - public Stream convertFrom(ProtobufReader in) { - SimpledCoder itemCoder = this.componentCoder; - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) itemCoder; - List data = new ArrayList<>(); - int len = in.readRawVarint32(); - while (len > 0) { - T val = itemCoder.convertFrom(in); - len -= primCoder.computeSize(val); - data.add(val); - } - return data.stream(); - } - - @Override - public int computeSize(ProtobufWriter out, int tagSize, Stream value) { - if (value == null) { - return 0; - } - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentCoder; - int len = 0; - for (Object item : value.toArray()) { - len += primCoder.computeSize(item); - } - return len; - } - - @Override - public final ProtobufTypeEnum typeEnum() { - return ProtobufTypeEnum.BYTES; - } - } - // ------------------------------------- boolean[] ------------------------------------- public static class ProtobufBoolArraySimpledCoder extends SimpledCoder implements ProtobufEncodeable { diff --git a/src/main/java/org/redkale/convert/pb/ProtobufCollectionDecoder.java b/src/main/java/org/redkale/convert/pb/ProtobufCollectionDecoder.java index d97963694..c51f77d14 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufCollectionDecoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufCollectionDecoder.java @@ -18,34 +18,41 @@ import org.redkale.convert.*; public class ProtobufCollectionDecoder extends CollectionDecoder implements ProtobufTagDecodeable> { + protected final boolean componentPrimitived; + protected final boolean componentSimpled; public ProtobufCollectionDecoder(ProtobufFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentDecoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentDecoder() instanceof SimpledCoder; } @Override public Collection convertFrom(ProtobufReader in, DeMember member) { this.checkInited(); - final boolean simpled = this.componentSimpled; + if (componentPrimitived) { + return convertPrimitivedFrom(in, member); + } else if (componentSimpled) { + return convertSimpledFrom(in, member); + } else { + return convertObjectFrom(in, member); + } + } + + protected Collection convertObjectFrom(ProtobufReader in, DeMember member) { final Decodeable itemDecoder = this.componentDecoder; in.readArrayB(itemDecoder); final Collection result = this.creator.create(); final int limit = in.limit(); while (in.hasNext()) { - boolean nodata = false; - if (!simpled) { - int contentLen = in.readRawVarint32(); - if (contentLen == 0) { - nodata = true; - } else { - in.limit(in.position() + contentLen + 1); - } - } - if (nodata) { + // 读长度 + int contentLen = in.readRawVarint32(); + // 读数据 + if (contentLen == 0) { result.add(null); } else { + in.limit(in.position() + contentLen + 1); result.add(itemDecoder.convertFrom(in)); in.limit(limit); } @@ -56,4 +63,31 @@ public class ProtobufCollectionDecoder extends CollectionDecoder convertSimpledFrom(ProtobufReader in, DeMember member) { + final Decodeable itemDecoder = this.componentDecoder; + in.readArrayB(itemDecoder); + final Collection result = this.creator.create(); + while (in.hasNext()) { + // 读数据 + result.add(itemDecoder.convertFrom(in)); + if (!in.readNextTag(member)) { // 元素结束 + break; + } + } + in.readArrayE(); + return result; + } + + protected Collection convertPrimitivedFrom(ProtobufReader in, DeMember member) { + ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentDecoder; + Collection result = this.creator.create(); + int len = in.readRawVarint32(); + while (len > 0) { + T val = primCoder.convertFrom(in); + len -= primCoder.computeSize(val); + result.add(val); + } + return result; + } } diff --git a/src/main/java/org/redkale/convert/pb/ProtobufCollectionEncoder.java b/src/main/java/org/redkale/convert/pb/ProtobufCollectionEncoder.java index a751eea55..4c9fb04fa 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufCollectionEncoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufCollectionEncoder.java @@ -7,8 +7,8 @@ package org.redkale.convert.pb; import java.lang.reflect.Type; import java.util.Collection; +import org.redkale.annotation.Nonnull; import org.redkale.convert.*; -import org.redkale.util.Utility; /** * @author zhangjx @@ -17,21 +17,30 @@ import org.redkale.util.Utility; public class ProtobufCollectionEncoder extends CollectionEncoder implements ProtobufEncodeable> { - protected final boolean componentSimpled; - protected final boolean componentSizeRequired; + protected final boolean componentPrimitived; - public ProtobufCollectionEncoder(ProtobufFactory factory, Type type) { + protected final boolean componentSimpled; + + public ProtobufCollectionEncoder(ConvertFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentEncoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentEncoder() instanceof SimpledCoder; - this.componentSizeRequired = !(getComponentEncoder() instanceof ProtobufPrimitivable); } @Override - public void convertTo(final ProtobufWriter out, EnMember member, Collection value) { + public void convertTo(final ProtobufWriter out, @Nonnull EnMember member, Collection value) { this.checkInited(); - if (Utility.isEmpty(value)) { + if (value == null || value.isEmpty()) { return; } + if (componentPrimitived) { + convertPrimitivedTo(out, member, value); + } else { + convertObjectTo(out, member, value); + } + } + + protected void convertObjectTo(final ProtobufWriter out, @Nonnull EnMember member, Collection value) { ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; out.writeArrayB(value.size(), itemEncoder, value); boolean first = true; @@ -49,25 +58,38 @@ public class ProtobufCollectionEncoder extends CollectionEncoder value) { + out.writeLength(computeSize(out, 0, value)); + Encodeable itemCoder = getComponentEncoder(); + for (T item : value) { + itemCoder.convertTo(out, item); + } + } + @Override public int computeSize(ProtobufWriter out, int tagSize, Collection value) { if (value == null || value.isEmpty()) { return 0; } - int dataSize = 0; ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; - for (T item : value) { - dataSize += itemEncoder.computeSize(out, tagSize, item); + if (componentPrimitived) { + int dataSize = 0; + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return dataSize; + } else { + int dataSize = tagSize * value.size(); + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return ProtobufFactory.computeSInt32SizeNoTag(dataSize) + dataSize; } - if (componentSizeRequired) { - dataSize += tagSize * value.size(); - } - return ProtobufFactory.computeSInt32SizeNoTag(dataSize) + dataSize; } @Override public boolean requireSize() { - return !componentSimpled; + return !componentPrimitived; } @Override diff --git a/src/main/java/org/redkale/convert/pb/ProtobufFactory.java b/src/main/java/org/redkale/convert/pb/ProtobufFactory.java index 9c5958c0d..64ce75dcd 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufFactory.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufFactory.java @@ -214,13 +214,6 @@ public class ProtobufFactory extends ConvertFactory creator = loadCreator(createClazz); return (Decodeable) new ProtobufCoders.ProtobufDoubleCollectionSimpledCoder(creator); - } else { - Decodeable componentCoder = findDecoder(componentType); - if (componentCoder instanceof ProtobufPrimitivable) { - Creator creator = loadCreator(createClazz); - ProtobufPrimitivable primCoder = (ProtobufPrimitivable) componentCoder; - return (Decodeable) new ProtobufCoders.ProtobufPrimitiveCollectionSimpledCoder(creator, primCoder); - } } return new ProtobufCollectionDecoder(this, type); } @@ -245,12 +238,6 @@ public class ProtobufFactory extends ConvertFactory extends MapEncoder out.writeMapB(values.size(), kencoder, vencoder, value); AtomicBoolean first = new AtomicBoolean(true); values.forEach((key, val0) -> { - if (ignoreColumns == null || !ignoreColumns.contains(key)) { + if (ignoreColumns == null || !ignoreColumns.contains(key.toString())) { V val = mapFieldFunc == null ? val0 : mapFieldFunc.apply(key, val0); if (!first.get()) { out.writeField(member); @@ -82,16 +82,6 @@ public class ProtobufMapEncoder extends MapEncoder out.writeMapE(); } - protected ProtobufWriter acceptWriter(ProtobufWriter out, EnMember member) { - return member != null ? out.pollChild() : out; - } - - protected void offerWriter(ProtobufWriter parent, ProtobufWriter out) { - if (parent != out) { - parent.offerChild(out); - } - } - public int computeSize(ProtobufWriter out, K key, V val) { ProtobufEncodeable kencoder = (ProtobufEncodeable) this.keyEncoder; ProtobufEncodeable vencoder = (ProtobufEncodeable) this.valueEncoder; @@ -110,7 +100,7 @@ public class ProtobufMapEncoder extends MapEncoder BiFunction mapFieldFunc = out.mapFieldFunc(); AtomicInteger size = new AtomicInteger(); value.forEach((key, val0) -> { - if (ignoreColumns == null || !ignoreColumns.contains(key)) { + if (ignoreColumns == null || !ignoreColumns.contains(key.toString())) { V val = mapFieldFunc == null ? val0 : mapFieldFunc.apply(key, val0); if (val != null) { size.addAndGet(tagSize); diff --git a/src/main/java/org/redkale/convert/pb/ProtobufPrimitivable.java b/src/main/java/org/redkale/convert/pb/ProtobufPrimitivable.java index aec992431..18a909550 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufPrimitivable.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufPrimitivable.java @@ -4,12 +4,15 @@ */ package org.redkale.convert.pb; +import org.redkale.convert.Decodeable; +import org.redkale.convert.Encodeable; + /** * 只能用于基本类型, 不能用于如String的其他类型 * @author zhangjx * @param 基本类型泛型 */ -public interface ProtobufPrimitivable { +public interface ProtobufPrimitivable extends Decodeable, Encodeable { // 获取java类型分类 public Class primitiveType(); diff --git a/src/main/java/org/redkale/convert/pb/ProtobufStreamDecoder.java b/src/main/java/org/redkale/convert/pb/ProtobufStreamDecoder.java index 45c7a4105..0c5ecc885 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufStreamDecoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufStreamDecoder.java @@ -17,34 +17,41 @@ import org.redkale.convert.*; public class ProtobufStreamDecoder extends StreamDecoder implements ProtobufTagDecodeable> { + protected final boolean componentPrimitived; + protected final boolean componentSimpled; public ProtobufStreamDecoder(ConvertFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentDecoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentDecoder() instanceof SimpledCoder; } @Override public Stream convertFrom(ProtobufReader in, DeMember member) { this.checkInited(); - final boolean simpled = this.componentSimpled; + if (componentPrimitived) { + return convertPrimitivedFrom(in, member); + } else if (componentSimpled) { + return convertSimpledFrom(in, member); + } else { + return convertObjectFrom(in, member); + } + } + + protected Stream convertObjectFrom(ProtobufReader in, DeMember member) { final Decodeable itemDecoder = this.componentDecoder; in.readArrayB(itemDecoder); final List result = new ArrayList(); final int limit = in.limit(); while (in.hasNext()) { - boolean nodata = false; - if (!simpled) { - int contentLen = in.readRawVarint32(); - if (contentLen == 0) { - nodata = true; - } else { - in.limit(in.position() + contentLen + 1); - } - } - if (nodata) { + // 读长度 + int contentLen = in.readRawVarint32(); + // 读数据 + if (contentLen == 0) { result.add(null); } else { + in.limit(in.position() + contentLen + 1); result.add(itemDecoder.convertFrom(in)); in.limit(limit); } @@ -55,4 +62,31 @@ public class ProtobufStreamDecoder extends StreamDecoder in.readArrayE(); return result.stream(); } + + protected Stream convertSimpledFrom(ProtobufReader in, DeMember member) { + final Decodeable itemDecoder = this.componentDecoder; + in.readArrayB(itemDecoder); + final List result = new ArrayList(); + while (in.hasNext()) { + // 读数据 + result.add(itemDecoder.convertFrom(in)); + if (!in.readNextTag(member)) { // 元素结束 + break; + } + } + in.readArrayE(); + return result.stream(); + } + + protected Stream convertPrimitivedFrom(ProtobufReader in, DeMember member) { + ProtobufPrimitivable primCoder = (ProtobufPrimitivable) this.componentDecoder; + List result = new ArrayList<>(); + int len = in.readRawVarint32(); + while (len > 0) { + T val = primCoder.convertFrom(in); + len -= primCoder.computeSize(val); + result.add(val); + } + return result.stream(); + } } diff --git a/src/main/java/org/redkale/convert/pb/ProtobufStreamEncoder.java b/src/main/java/org/redkale/convert/pb/ProtobufStreamEncoder.java index 00275360e..73461071e 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufStreamEncoder.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufStreamEncoder.java @@ -17,26 +17,35 @@ import org.redkale.convert.*; public class ProtobufStreamEncoder extends StreamEncoder implements ProtobufEncodeable> { + protected final boolean componentPrimitived; + protected final boolean componentSimpled; - protected final boolean componentSizeRequired; public ProtobufStreamEncoder(ConvertFactory factory, Type type) { super(factory, type); + this.componentPrimitived = getComponentEncoder() instanceof ProtobufPrimitivable; this.componentSimpled = getComponentEncoder() instanceof SimpledCoder; - this.componentSizeRequired = !(getComponentEncoder() instanceof ProtobufPrimitivable); } @Override public void convertTo(final ProtobufWriter out, @Nonnull EnMember member, Stream value) { this.checkInited(); - Object[] array = value == null ? null : value.toArray(); + Object[] array = out.getStreamArray(value); if (array == null || array.length < 1) { return; } + if (componentPrimitived) { + convertPrimitivedTo(out, member, array); + } else { + convertObjectTo(out, member, array); + } + } + + protected void convertObjectTo(final ProtobufWriter out, @Nonnull EnMember member, Object[] value) { ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; - out.writeArrayB(array.length, itemEncoder, array); + out.writeArrayB(value.length, itemEncoder, value); boolean first = true; - for (Object item : array) { + for (Object item : value) { if (!first) { out.writeField(member); } @@ -50,15 +59,43 @@ public class ProtobufStreamEncoder extends StreamEncoder out.writeArrayE(); } + protected void convertPrimitivedTo(final ProtobufWriter out, @Nonnull EnMember member, Object[] value) { + out.writeLength(computeSize(out, 0, value)); + Encodeable itemCoder = getComponentEncoder(); + for (Object item : value) { + itemCoder.convertTo(out, (T) item); + } + } + @Override public int computeSize(ProtobufWriter out, int tagSize, Stream value) { - // Stream被forEach之后就不可用了, 所以不能进行遍历 - throw new UnsupportedOperationException("Not supported yet."); + Object[] array = out.putStreamArray(value); + if (array == null || array.length < 1) { + return 0; + } + return computeSize(out, tagSize, array); + } + + protected int computeSize(ProtobufWriter out, int tagSize, Object[] value) { + ProtobufEncodeable itemEncoder = (ProtobufEncodeable) this.componentEncoder; + if (componentPrimitived) { + int dataSize = 0; + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return dataSize; + } else { + int dataSize = tagSize * value.length; + for (Object item : value) { + dataSize += itemEncoder.computeSize(out, tagSize, item); + } + return ProtobufFactory.computeSInt32SizeNoTag(dataSize) + dataSize; + } } @Override public boolean requireSize() { - return !componentSimpled; + return !componentPrimitived; } @Override diff --git a/src/main/java/org/redkale/convert/pb/ProtobufWriter.java b/src/main/java/org/redkale/convert/pb/ProtobufWriter.java index 41926b8c8..a88e5aae1 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufWriter.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufWriter.java @@ -70,6 +70,8 @@ public abstract class ProtobufWriter extends Writer { protected ProtobufBytesWriter child; + protected Map streamArrayCache; + protected ProtobufWriter() {} @Override @@ -111,6 +113,7 @@ public abstract class ProtobufWriter extends Writer { this.features = 0; this.enumtostring = false; this.count = 0; + this.streamArrayCache = null; return true; } @@ -138,6 +141,32 @@ public abstract class ProtobufWriter extends Writer { return count; } + public final @Nullable Object[] putStreamArray(Stream stream) { + if (stream == null) { + return null; + } + if (this.streamArrayCache == null) { + this.streamArrayCache = new HashMap<>(); + } + Object[] rs = stream.toArray(); + this.streamArrayCache.put(stream, rs); + return rs; + } + + public final @Nullable Object[] getStreamArray(Stream stream) { + if (stream == null) { + return null; + } + if (this.streamArrayCache == null) { + return stream.toArray(); + } + Object[] rs = this.streamArrayCache.get(stream); + if (rs == null) { + rs = stream.toArray(); + } + return rs; + } + @Override public String toString() { return this.getClass().getSimpleName() + "@" + Objects.hashCode(this) + "[count=" + this.count + "]";