TBR java: add support for length for any messages to encoding format
MultiPart: 3/4
Change-Id: I861bf21e3596210f7e089552c522391f46bf395f
diff --git a/lib/src/main/java/io/v/v23/vom/BinaryDecoder.java b/lib/src/main/java/io/v/v23/vom/BinaryDecoder.java
index 9b9005b..b4c011d 100644
--- a/lib/src/main/java/io/v/v23/vom/BinaryDecoder.java
+++ b/lib/src/main/java/io/v/v23/vom/BinaryDecoder.java
@@ -108,13 +108,19 @@
private Object readValueMessage(VdlType actualType, Type targetType) throws IOException,
ConversionException {
- if (version != Version.Version80 && BinaryUtil.hasAnyOrTypeObject(actualType)) {
+ if (version != Version.Version80 && (BinaryUtil.hasAny(actualType) || BinaryUtil.hasTypeObject(actualType))) {
long len = BinaryUtil.decodeUint(in);
typeIds = new long[(int)len];
for (int i = 0; i < len; i++) {
typeIds[i] = BinaryUtil.decodeUint(in);
}
}
+ if (version != Version.Version80 && BinaryUtil.hasAny(actualType)) {
+ long len = BinaryUtil.decodeUint(in);
+ for (int i = 0; i < len; i++) {
+ BinaryUtil.decodeUint(in); // read anyMsgLen (ignore value -- it is unused)
+ }
+ }
if (BinaryUtil.hasBinaryMsgLen(actualType)) {
// Do nothing with this information for now.
BinaryUtil.decodeUint(in);
@@ -270,6 +276,7 @@
typeId = BinaryUtil.decodeUint(in);
} else {
typeId = typeIds[(int)BinaryUtil.decodeUint(in)];
+ BinaryUtil.decodeUint(in); // read anyLen index (ignore for now -- unused)
}
VdlType actualType = getType(new TypeId(typeId));
if (target.getKind() == Kind.ANY) {
diff --git a/lib/src/main/java/io/v/v23/vom/BinaryEncoder.java b/lib/src/main/java/io/v/v23/vom/BinaryEncoder.java
index ec724b2..4296d00 100644
--- a/lib/src/main/java/io/v/v23/vom/BinaryEncoder.java
+++ b/lib/src/main/java/io/v/v23/vom/BinaryEncoder.java
@@ -59,6 +59,7 @@
private boolean binaryMagicByteWritten;
private Version version;
private List<Long> typeIds;
+ private List<Long> anyLens;
public BinaryEncoder(OutputStream out) {
this(out, Version.DEFAULT_VERSION);
@@ -88,9 +89,11 @@
}
valueBuffer.reset();
typeIds = new ArrayList<Long>();
+ anyLens = new ArrayList<Long>();
TypeId typeId = getType(type);
writeValue(valueBuffer, value, type);
- writeMessage(valueBuffer, BinaryUtil.hasAnyOrTypeObject(type), false, typeId.getValue(), BinaryUtil.hasBinaryMsgLen(type));
+ writeMessage(valueBuffer, BinaryUtil.hasAny(type), BinaryUtil.hasTypeObject(type),
+ false, typeId.getValue(), BinaryUtil.hasBinaryMsgLen(type));
}
/**
@@ -114,20 +117,27 @@
encodeValue(value.vdlType(), value);
}
- private void writeMessage(ByteArrayOutputStream buffer, boolean hasAnyOrTypeObject, boolean typeIncomplete,
- long messageId, boolean encodeLength)
+ private void writeMessage(ByteArrayOutputStream buffer, boolean hasAny, boolean hasTypeObject,
+ boolean typeIncomplete, long messageId, boolean encodeLength)
throws IOException {
if (version != Version.Version80 && typeIncomplete) {
out.write(Constants.WIRE_CTRL_TYPE_INCOMPLETE);
}
BinaryUtil.encodeInt(out, messageId);
- if (version != Version.Version80 && hasAnyOrTypeObject && messageId > 0) {
+ if (version != Version.Version80 && (hasAny || hasTypeObject) && messageId > 0) {
BinaryUtil.encodeUint(out, typeIds.size());
for (Long id : typeIds) {
BinaryUtil.encodeUint(out, id);
}
typeIds = null;
}
+ if (version != Version.Version80 && hasAny && messageId > 0) {
+ BinaryUtil.encodeUint(out, anyLens.size());
+ for (Long len : anyLens) {
+ BinaryUtil.encodeUint(out, len);
+ }
+ anyLens = null;
+ }
if (encodeLength) {
BinaryUtil.encodeUint(out, buffer.size());
}
@@ -160,7 +170,8 @@
boolean incomplete = typeIncomplete(type, pending, new HashSet<VdlType>());
typeBuffer.reset();
writeValue(typeBuffer, wireType, wireType.vdlType());
- writeMessage(typeBuffer, BinaryUtil.hasAnyOrTypeObject(type), incomplete, -typeId.getValue(), true);
+ writeMessage(typeBuffer, BinaryUtil.hasAny(type), BinaryUtil.hasTypeObject(type),
+ incomplete, -typeId.getValue(), true);
return typeId;
}
@@ -332,7 +343,19 @@
if (elem != null) {
long id = getType(anyValue.getElemType()).getValue();
writeTypeId(out, id);
+ int anyLenIndex = -1;
+ long startPos = -1;
+ if (version != Version.Version80) {
+ anyLenIndex = anyLens.size();
+ BinaryUtil.encodeUint(out, anyLenIndex);
+ anyLens.add(0L);
+ startPos = out.getCount();
+ }
writeValue(out, elem, anyValue.getElemType());
+ if (version != Version.Version80) {
+ long endPos = out.getCount();
+ anyLens.set(anyLenIndex, endPos - startPos);
+ }
return true;
} else {
writeVdlControlByte(out, Constants.WIRE_CTRL_NIL);
diff --git a/lib/src/main/java/io/v/v23/vom/BinaryUtil.java b/lib/src/main/java/io/v/v23/vom/BinaryUtil.java
index 93b6fd7..cb8fa43 100644
--- a/lib/src/main/java/io/v/v23/vom/BinaryUtil.java
+++ b/lib/src/main/java/io/v/v23/vom/BinaryUtil.java
@@ -172,11 +172,46 @@
}
}
- static boolean hasAnyOrTypeObject(VdlType t) {
- return hasAnyOrTypeObjectInternal(t, new HashSet<VdlType>());
+ static boolean hasTypeObject(VdlType t) {
+ return hasTypeObjectInternal(t, new HashSet<VdlType>());
}
- private static boolean hasAnyOrTypeObjectInternal(VdlType t, HashSet<VdlType> seen) {
+ private static boolean hasTypeObjectInternal(VdlType t, HashSet<VdlType> seen) {
+ if (seen.contains(t)) {
+ return false;
+ }
+ seen.add(t);
+
+ switch (t.getKind()) {
+ case TYPEOBJECT:
+ return true;
+ case OPTIONAL:
+ case LIST:
+ case ARRAY:
+ return hasTypeObjectInternal(t.getElem(), seen);
+ case SET:
+ return hasTypeObjectInternal(t.getKey(), seen);
+ case MAP:
+ return hasTypeObjectInternal(t.getKey(), seen) ||
+ hasTypeObjectInternal(t.getElem(), seen);
+ case STRUCT:
+ case UNION:
+ for (VdlField fld : t.getFields()) {
+ if (hasTypeObjectInternal(fld.getType(), seen)) {
+ return true;
+ }
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ static boolean hasAny(VdlType t) {
+ return hasAnyInternal(t, new HashSet<VdlType>());
+ }
+
+ private static boolean hasAnyInternal(VdlType t, HashSet<VdlType> seen) {
if (seen.contains(t)) {
return false;
}
@@ -184,21 +219,20 @@
switch (t.getKind()) {
case ANY:
- case TYPEOBJECT:
return true;
case OPTIONAL:
case LIST:
case ARRAY:
- return hasAnyOrTypeObjectInternal(t.getElem(), seen);
+ return hasAnyInternal(t.getElem(), seen);
case SET:
- return hasAnyOrTypeObjectInternal(t.getKey(), seen);
+ return hasAnyInternal(t.getKey(), seen);
case MAP:
- return hasAnyOrTypeObjectInternal(t.getKey(), seen) ||
- hasAnyOrTypeObjectInternal(t.getElem(), seen);
+ return hasAnyInternal(t.getKey(), seen) ||
+ hasAnyInternal(t.getElem(), seen);
case STRUCT:
case UNION:
for (VdlField fld : t.getFields()) {
- if (hasAnyOrTypeObjectInternal(fld.getType(), seen)) {
+ if (hasAnyInternal(fld.getType(), seen)) {
return true;
}
}