shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(0, edit, edit.cellType(), edit.cellTypeArgs(), RowOptions.DELETE, metaBytes, spaceNeeded, shift);
- this.buffer.writerIndex(this.length() + shift.get());
+
+ checkState(this.length() == priorLength + shift.get());
}
+ /**
+ * Delete the variable-length field at a specified {@code offset}
+ *
+ * The field is interpreted as either a variable-length integer or a variable-length sequence of bytes as indicated
+ * by the value of {@code isVarint}.
+ *
+ * @param offset index of the field in this {@link RowBuffer}
+ * @param isVarint {@code true}, if the field should be interpreted as a variable-length integer value;
+ * {@code false}, if the field should be interpreted as a variable-length sequence of bytes.
+ */
public void deleteVariable(final int offset, final boolean isVarint) {
- int start = this.buffer.readerIndex();
- this.read7BitEncodedUInt();
+ final Item item = this.read(this::read7BitEncodedUInt, offset);
- ByteBuf remainder = this.buffer.slice(this.buffer.readerIndex(), this.buffer.readableBytes());
- this.buffer.readerIndex(start);
- this.buffer.setBytes(start, remainder);
- this.buffer.writerIndex(start + remainder.readableBytes());
+ final int source = isVarint
+ ? offset + item.length() // because this is a varint value
+ : offset + item.length() + item.value().intValue(); // because this is a variable-length sequence of bytes
+
+ final int length = this.buffer.writerIndex() - source;
+
+ this.buffer.setBytes(offset, this.buffer, source, length);
+ this.buffer.writerIndex(this.buffer.writerIndex() - length);
}
/**
@@ -684,6 +543,11 @@ public final class RowBuffer {
this.buffer.setIntLE(offset, (int) (value + increment));
}
+ // TODO: DANOBLE: resurrect this method
+ // public MongoDbObjectId ReadMongoDbObjectId(int offset) {
+ // return MemoryMarshal.Read(this.buffer.Slice(offset));
+ // }
+
/**
* Initializes a row to the minimal size for the given layout.
*
@@ -706,18 +570,11 @@ public final class RowBuffer {
this.resolver = resolver;
}
- // TODO: DANOBLE: resurrect this method
- // public MongoDbObjectId ReadSparseMongoDbObjectId(Reference edit) {
- // this.readSparsePrimitiveTypeCode(edit, MongoDbObjectId);
- // edit.endOffset = edit.valueOffset() + MongoDbObjectId.Size;
- // return this.ReadMongoDbObjectId(edit.valueOffset()).clone();
- // }
-
/**
- * The length of this {@link RowBuffer} in bytes.
+ * The length of this {@link RowBuffer} in bytes
*/
public int length() {
- return this.buffer.readerIndex() + this.buffer.readableBytes();
+ return this.buffer.writerIndex();
}
/**
@@ -795,6 +652,13 @@ public final class RowBuffer {
return item.value();
}
+ // TODO: DANOBLE: resurrect this method
+ // public MongoDbObjectId ReadSparseMongoDbObjectId(Reference edit) {
+ // this.readSparsePrimitiveTypeCode(edit, MongoDbObjectId);
+ // edit.endOffset = edit.valueOffset() + MongoDbObjectId.Size;
+ // return this.ReadMongoDbObjectId(edit.valueOffset()).clone();
+ // }
+
public OffsetDateTime readDateTime(int offset) {
Item item = this.read(() -> DateTimeCodec.decode(this.buffer), offset);
return item.value();
@@ -1108,14 +972,6 @@ public final class RowBuffer {
return item.value();
}
- // TODO: DANOBLE: Support MongoDbObjectId values
- // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) {
- // Reference tempReference_value =
- // new Reference(value);
- // MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value);
- // value = tempReference_value.get();
- // }
-
public long readUInt32(int offset) {
Item item = this.read(this.buffer::readUnsignedIntLE, offset);
return item.value();
@@ -1141,6 +997,14 @@ public final class RowBuffer {
return item.value();
}
+ // TODO: DANOBLE: Support MongoDbObjectId values
+ // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) {
+ // Reference tempReference_value =
+ // new Reference(value);
+ // MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value);
+ // value = tempReference_value.get();
+ // }
+
public long readVariableInt(int offset) {
Item item = this.read(this::read7BitEncodedInt, offset);
return item.value();
@@ -1236,7 +1100,8 @@ public final class RowBuffer {
* If found, the offset to the value of the field, otherwise
* undefined.
* .
- * @return True if there is another field, false if there are no more.
+ *
+ * @return {@code true} if there is another field; {@code false} if there is not.
*/
public boolean sparseIteratorMoveNext(RowCursor edit) {
@@ -1371,7 +1236,7 @@ public final class RowBuffer {
if (scopeType instanceof LayoutUDT) {
final Layout udt = this.resolver.resolve(edit.cellTypeArgs().schemaId());
- final int valueOffset = this.ComputeVariableValueOffset(udt, edit.valueOffset(), udt.numVariable());
+ final int valueOffset = this.computeVariableValueOffset(udt, edit.valueOffset(), udt.numVariable());
return new RowCursor()
.scopeType(scopeType)
@@ -1464,11 +1329,10 @@ public final class RowBuffer {
}, offset, value);
}
- @SuppressWarnings("ConstantConditions")
public void writeFixedString(final int offset, @Nonnull final Utf8String value) {
checkNotNull(value, "expected non-null value");
checkArgument(!value.isNull(), "expected non-null value content");
- Item item = this.write(this.buffer::writeBytes, offset, value.content());
+ Item item = this.write(this::writeFixedString, offset, value);
}
public void writeFloat128(int offset, Float128 value) {
@@ -1510,51 +1374,54 @@ public final class RowBuffer {
this.buffer.writeByte(value);
}
- public void writeNullable(
+ @Nonnull
+ public RowCursor writeNullable(
@Nonnull final RowCursor edit,
- @Nonnull final LayoutScope scopeType,
+ @Nonnull final LayoutScope scope,
@Nonnull final TypeArgumentList typeArgs,
@Nonnull final UpdateOptions options,
- boolean hasValue,
- @Nonnull final Out newScope) {
+ boolean hasValue) {
checkNotNull(edit, "expected non-null edit");
- checkNotNull(scopeType, "expected non-null scopeType");
+ checkNotNull(scope, "expected non-null scope");
checkNotNull(typeArgs, "expected non-null typeArgs");
checkNotNull(options, "expected non-null options");
- checkNotNull(newScope, "expected non-null newScope");
- final int length = this.countDefaultValue(scopeType, typeArgs);
+ final int length = this.countDefaultValue(scope, typeArgs);
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, scopeType, typeArgs, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, scopeType, typeArgs, metaBytes.get());
- final int numWritten = this.writeDefaultValue(edit.valueOffset(), scopeType, typeArgs);
+ final int priorLength = this.length();
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
+
+ final int numWritten = this.writeDefaultValue(edit.valueOffset(), scope, typeArgs);
checkState(length == numWritten);
- checkState(spaceNeeded.get() == metaBytes.get() + length);
if (hasValue) {
this.writeInt8(edit.valueOffset(), (byte) 1);
}
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
final int valueOffset = edit.valueOffset() + 1;
- newScope.setAndGet(new RowCursor()
- .scopeType(scopeType)
+ RowCursor newScope = new RowCursor()
+ .scopeType(scope)
.scopeTypeArgs(typeArgs)
.start(edit.valueOffset())
.valueOffset(valueOffset)
.metaOffset(valueOffset)
.layout(edit.layout())
.count(2)
- .index(1));
+ .index(1);
- this.buffer.writerIndex(this.length() + shift.get());
- RowCursors.moveNext(newScope.get(), this);
+ RowCursors.moveNext(newScope, this);
+ return newScope;
}
public void writeSchemaId(final int offset, @Nonnull final SchemaId value) {
@@ -1562,6 +1429,39 @@ public final class RowBuffer {
this.writeInt32(offset, value.value());
}
+ @Nonnull
+ public RowCursor writeSparseArray(
+ @Nonnull final RowCursor edit, @Nonnull final LayoutScope scope, @Nonnull final UpdateOptions options) {
+
+ checkNotNull(edit, "expected non-null edit");
+ checkNotNull(scope, "expected non-null scopeType");
+ checkNotNull(options, "expected non-null options");
+
+ int length = LayoutCode.BYTES;
+ TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
+
+ final Out metaBytes = new Out<>();
+ final Out spaceNeeded = new Out<>();
+ final Out shift = new Out<>();
+
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
+ this.writeSparseTypeCode(edit.valueOffset(), LayoutCode.END_SCOPE);
+
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
+ return new RowCursor()
+ .scopeType(scope)
+ .scopeTypeArgs(typeArgs)
+ .start(edit.valueOffset())
+ .valueOffset(edit.valueOffset())
+ .metaOffset(edit.valueOffset())
+ .layout(edit.layout());
+ }
+
public void writeSparseBinary(
@Nonnull final RowCursor edit, @Nonnull final ByteBuf value, @Nonnull final UpdateOptions options) {
@@ -1569,19 +1469,22 @@ public final class RowBuffer {
checkNotNull(value, "expected non-null value");
checkNotNull(options, "expected non-null options");
+ final int length = RowBuffer.count7BitEncodedUInt(value.readableBytes()) + value.readableBytes();
final LayoutType type = LayoutTypes.BINARY;
- final int readableBytes = value.readableBytes();
- final int length = RowBuffer.count7BitEncodedUInt(readableBytes) + readableBytes;
final Out metaBytes = new Out<>();
final Out shift = new Out<>();
final Out spaceNeeded = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeVariableBinary(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
}
@@ -1591,17 +1494,22 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = value ? LayoutTypes.BOOLEAN : LayoutTypes.BOOLEAN_FALSE;
final int length = 0;
+ final LayoutType type = value ? LayoutTypes.BOOLEAN : LayoutTypes.BOOLEAN_FALSE;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get());
+
+ checkState(spaceNeeded.get() == (int) metaBytes.get());
+ checkState(this.length() == priorLength + shift.get());
- checkState(spaceNeeded.get().equals(metaBytes.get()));
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
}
@@ -1619,13 +1527,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeDateTime(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseDecimal(
@@ -1642,13 +1553,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeDecimal(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseFloat128(
@@ -1665,13 +1579,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeFloat128(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseFloat32(@Nonnull RowCursor edit, float value, @Nonnull UpdateOptions options) {
@@ -1686,13 +1603,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeFloat32(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseFloat64(@Nonnull final RowCursor edit, double value, @Nonnull final UpdateOptions options) {
@@ -1707,13 +1627,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeFloat64(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseGuid(
@@ -1730,13 +1653,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, LayoutTypes.GUID, TypeArgumentList.EMPTY, metaBytes.get());
+ this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeGuid(edit.valueOffset(), value);
- checkState(spaceNeeded.get() == metaBytes.get() + 16);
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseInt16(@Nonnull final RowCursor edit, short value, @Nonnull final UpdateOptions options) {
@@ -1751,13 +1677,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeInt16(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseInt32(@Nonnull final RowCursor edit, int value, @Nonnull final UpdateOptions options) {
@@ -1772,13 +1701,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeInt32(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseInt64(@Nonnull final RowCursor edit, long value, UpdateOptions options) {
@@ -1793,13 +1725,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeInt64(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseInt8(@Nonnull final RowCursor edit, byte value, UpdateOptions options) {
@@ -1807,20 +1742,24 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = LayoutTypes.INT_8;
final int length = Long.BYTES;
+ final LayoutType type = LayoutTypes.INT_8;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get());
this.writeInt8(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseNull(
@@ -1829,31 +1768,33 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = LayoutTypes.NULL;
final int length = 0;
+ final LayoutType type = LayoutTypes.NULL;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get());
checkState(spaceNeeded.get() == (int)metaBytes.get());
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
- public void writeSparseObject(
+ public RowCursor writeSparseObject(
@Nonnull final RowCursor edit,
- @Nonnull final LayoutScope scopeType,
- @Nonnull final UpdateOptions options,
- @Nonnull final Out newScope) {
+ @Nonnull final LayoutScope scope,
+ @Nonnull final UpdateOptions options) {
checkNotNull(edit, "expected non-null edit");
- checkNotNull(options, "expected non-null scopeType");
+ checkNotNull(scope, "expected non-null scope");
checkNotNull(options, "expected non-null options");
- checkNotNull(options, "expected non-null newScope");
int length = LayoutCode.BYTES; // end scope type code.
TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
@@ -1862,21 +1803,85 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, scopeType, typeArgs, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, scopeType, TypeArgumentList.EMPTY, metaBytes.get());
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
this.writeSparseTypeCode(edit.valueOffset(), LayoutCode.END_SCOPE);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
- newScope.setAndGet(new RowCursor()
- .scopeType(scopeType)
+ return new RowCursor()
+ .scopeType(scope)
.scopeTypeArgs(TypeArgumentList.EMPTY)
.start(edit.valueOffset())
.valueOffset(edit.valueOffset())
.metaOffset(edit.valueOffset())
- .layout(edit.layout()));
+ .layout(edit.layout());
+ }
- this.buffer.writerIndex(this.length() + shift.get());
+ public void writeSparseString(
+ @Nonnull final RowCursor edit, @Nonnull final Utf8String value, @Nonnull final UpdateOptions options) {
+
+ final LayoutType type = LayoutTypes.UTF_8;
+ final TypeArgumentList args = TypeArgumentList.EMPTY;
+ final int length = RowBuffer.count7BitEncodedUInt(value.encodedLength()) + value.encodedLength();
+
+ final Out metaBytes = new Out<>();
+ final Out spaceNeeded = new Out<>();
+ final Out shift = new Out<>();
+
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, type, args, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, type, args, metaBytes.get());
+ this.write(this::writeVariableString, edit.valueOffset(), value);
+
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
+ edit.endOffset(edit.metaOffset() + spaceNeeded.get());
+ }
+
+ @Nonnull
+ public RowCursor writeSparseTuple(
+ @Nonnull final RowCursor edit,
+ @Nonnull final LayoutScope scope,
+ @Nonnull final TypeArgumentList typeArgs,
+ @Nonnull final UpdateOptions options) {
+
+ int length = LayoutCode.BYTES * (1 + typeArgs.count()); // nulls for each element
+
+ final Out metaBytes = new Out<>();
+ final Out spaceNeeded = new Out<>();
+ final Out shift = new Out<>();
+
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
+
+ int valueOffset = edit.valueOffset();
+
+ for (int i = 0; i < typeArgs.count(); i++) {
+ this.writeSparseTypeCode(valueOffset, LayoutCode.NULL);
+ valueOffset += LayoutCode.BYTES;
+ }
+
+ this.writeSparseTypeCode(valueOffset, LayoutCode.END_SCOPE);
+
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
+ return new RowCursor()
+ .scopeType(scope)
+ .scopeTypeArgs(typeArgs)
+ .start(edit.valueOffset())
+ .valueOffset(edit.valueOffset())
+ .metaOffset(edit.valueOffset())
+ .layout(edit.layout())
+ .count(typeArgs.count());
}
public void writeSparseTypeCode(int offset, LayoutCode code) {
@@ -1889,20 +1894,24 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = LayoutTypes.UINT_16;
final int length = Short.BYTES;
+ final LayoutType type = LayoutTypes.UINT_16;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeUInt16(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseUInt32(
@@ -1911,20 +1920,24 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = LayoutTypes.UINT_32;
final int length = Integer.BYTES;
+ final LayoutType type = LayoutTypes.UINT_32;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeUInt32(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseUInt64(@Nonnull final RowCursor edit, long value, @Nonnull UpdateOptions options) {
@@ -1932,20 +1945,24 @@ public final class RowBuffer {
checkNotNull(edit, "expected non-null edit");
checkNotNull(options, "expected non-null options");
- final LayoutType type = LayoutTypes.UINT_64;
final int length = Long.BYTES;
+ final LayoutType type = LayoutTypes.UINT_64;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeUInt64(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseUInt8(
@@ -1961,13 +1978,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeUInt8(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseUnixDateTime(
@@ -1984,13 +2004,16 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
this.writeUnixDateTime(edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseVarInt(@Nonnull final RowCursor edit, final long value, @Nonnull final UpdateOptions options) {
@@ -2005,36 +2028,39 @@ public final class RowBuffer {
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
+ final int priorLength = this.length();
+
this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
-
- final Item item = this.write(this::write7BitEncodedInt, edit.valueOffset(), value);
- checkState(item.length() == length);
+ this.write(this::write7BitEncodedInt, edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
public void writeSparseVarUInt(
@Nonnull final RowCursor edit, final long value, @Nonnull final UpdateOptions options) {
final LayoutType type = LayoutTypes.VAR_UINT;
+ final TypeArgumentList typeArgs = TypeArgumentList.EMPTY;
final int length = RowBuffer.count7BitEncodedUInt(value);
final Out metaBytes = new Out<>();
final Out spaceNeeded = new Out<>();
final Out shift = new Out<>();
- this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift);
- this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get());
+ final int priorLength = this.length();
- final Item item = this.write(this::write7BitEncodedUInt, edit.valueOffset(), value);
- checkState(item.length == length);
+ this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get());
+ this.write(this::write7BitEncodedUInt, edit.valueOffset(), value);
checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
edit.endOffset(edit.metaOffset() + spaceNeeded.get());
- this.buffer.writerIndex(this.length() + shift.get());
}
/**
@@ -2048,6 +2074,75 @@ public final class RowBuffer {
this.buffer.getBytes(0, stream, this.length());
}
+ @Nonnull
+ public RowCursor writeTypedSet(
+ @Nonnull final RowCursor edit,
+ @Nonnull final LayoutScope scope,
+ @Nonnull final TypeArgumentList typeArgs,
+ @Nonnull final UpdateOptions options) {
+
+ final int length = Integer.BYTES;
+
+ final Out metaBytes = new Out<>();
+ final Out spaceNeeded = new Out<>();
+ final Out shift = new Out<>();
+
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
+ this.writeUInt32(edit.valueOffset(), 0);
+
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
+ final int valueOffset = edit.valueOffset() + Integer.BYTES; // point after the size
+
+ return new RowCursor()
+ .scopeType(scope)
+ .scopeTypeArgs(typeArgs)
+ .start(edit.valueOffset())
+ .valueOffset(valueOffset)
+ .metaOffset(valueOffset)
+ .layout(edit.layout());
+ }
+
+ public RowCursor writeTypedTuple(
+ @Nonnull final RowCursor edit,
+ @Nonnull final LayoutScope scope,
+ @Nonnull final TypeArgumentList typeArgs,
+ @Nonnull final UpdateOptions options) {
+
+ final int length = this.countDefaultValue(scope, typeArgs);
+
+ final Out metaBytes = new Out<>();
+ final Out spaceNeeded = new Out<>();
+ final Out shift = new Out<>();
+
+ final int priorLength = this.length();
+
+ this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift);
+ this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get());
+
+ final int numWritten = this.writeDefaultValue(edit.valueOffset(), scope, typeArgs);
+ checkState(length == numWritten);
+
+ checkState(spaceNeeded.get() == metaBytes.get() + length);
+ checkState(this.length() == priorLength + shift.get());
+
+ final RowCursor newScope = new RowCursor()
+ .scopeType(scope)
+ .scopeTypeArgs(typeArgs)
+ .start(edit.valueOffset())
+ .valueOffset(edit.valueOffset())
+ .metaOffset(edit.valueOffset())
+ .layout(edit.layout())
+ .count(typeArgs.count());
+
+ RowCursors.moveNext(newScope, this);
+ return newScope;
+ }
+
public void writeUInt16(final int offset, final short value) {
final Item item = this.write(this::writeUInt16, offset, value);
}
@@ -2076,11 +2171,14 @@ public final class RowBuffer {
final int length = value.readableBytes();
final Out spaceNeeded = new Out<>();
- this.ensureVariable(offset, false, length, exists, spaceNeeded, shift);
+ final int priorLength = this.length();
+
+ this.ensureVariable(offset, false, length, exists, spaceNeeded, shift);
final Item item = this.write(this::writeVariableBinary, offset, value);
+
checkState(spaceNeeded.get() == length + item.length());
- this.buffer.writerIndex(this.length() + shift.get());
+ checkState(this.length() == priorLength + shift.get());
}
public void writeVariableInt(int offset, long value, boolean exists, Out shift) {
@@ -2090,12 +2188,14 @@ public final class RowBuffer {
final int length = RowBuffer.count7BitEncodedInt(value);
final Out spaceNeeded = new Out<>();
+ final int priorLength = this.length();
+
this.ensureVariable(offset, true, length, exists, spaceNeeded, shift);
final Item item = this.write(this::write7BitEncodedInt, offset, value);
checkState(item.length == length);
checkState(spaceNeeded.get() == length);
- this.buffer.writerIndex(this.length() + shift.get());
+ checkState(this.length() == priorLength + shift.get());
}
public void writeVariableString(
@@ -2108,11 +2208,14 @@ public final class RowBuffer {
final int length = value.encodedLength();
final Out spaceNeeded = new Out<>();
+
+ final int priorLength = this.length();
+
this.ensureVariable(offset, false, length, exists, spaceNeeded, shift);
Item item = this.write(this::writeVariableString, offset, value);
checkState(spaceNeeded.get() == length + item.length());
- this.buffer.writerIndex(this.length() + shift.get());
+ checkState(this.length() == priorLength + shift.get());
}
public void writeVariableUInt(
@@ -2124,86 +2227,61 @@ public final class RowBuffer {
final int length = RowBuffer.count7BitEncodedUInt(value);
final Out spaceNeeded = new Out<>();
+ final int priorLength = this.length();
+
this.ensureVariable(offset, true, length, exists, spaceNeeded, shift);
final Item item = this.write(this::write7BitEncodedUInt, offset, value);
checkState(item.length == length);
checkState(spaceNeeded.get() == length);
- this.buffer.writerIndex(this.length() + shift.get());
+ checkState(this.length() == priorLength + shift.get());
}
/**
- * Sorts the array structure using the hybrid row binary
- * collation.
+ * Compares the values of two encoded fields using the hybrid row binary collation.
*
- * @param scope The scope to be sorted.
- * @param dstEdit A edit that points at the scope.
- * @param uniqueIndex A unique index array structure that identifies the row offsets of each
- * element in the scope.
- * @return true if the array was sorted, false if a duplicate was found during sorting.
- *
- * Implementation Note:
- *
This method MUST guarantee that if at least one duplicate exists it will be found.
- * Insertion Sort is used for this purpose as it guarantees that each value is eventually compared
- * against its previous item in sorted order. If any two successive items are the same they must be
- * duplicates.
- *
- * Other search algorithms, such as Quick Sort or Merge Sort, may offer fewer comparisons in the
- * limit but don't necessarily guarantee that duplicates will be discovered. If an alternative
- * algorithm is used, then an independent duplicate pass MUST be employed.
- *
- *
- * Under the current operational assumptions, the expected cardinality of sets and maps is
- * expected to be relatively small. If this assumption changes, Insertion Sort may no longer be the
- * best choice.
- *
+ * @param left An edit describing the left field.
+ * @param leftLength The size of the left field's value in bytes.
+ * @param right An edit describing the right field.
+ * @param rightLength The size of the right field's value in bytes.
+ * @return
+ * -
+ * -1left less than right.
+ *
-
+ * 0left and right are equal.
+ *
-
+ * 1left is greater than right.
+ *
+ *
*/
- private boolean InsertionSort(Reference scope, Reference dstEdit,
- Span uniqueIndex) {
- RowCursor leftEdit = dstEdit.clone();
- RowCursor rightEdit = dstEdit.clone();
+ private int compareFieldValue(
+ @Nonnull final RowCursor left, final int leftLength, @Nonnull final RowCursor right, final int rightLength) {
- for (int i = 1; i < uniqueIndex.Length; i++) {
- UniqueIndexItem x = uniqueIndex[i];
- leftEdit.cellType = LayoutType.FromCode(x.code());
- leftEdit.metaOffset(x.metaOffset());
- leftEdit.valueOffset(x.valueOffset());
- int leftBytes = x.size() - (x.valueOffset() - x.metaOffset());
+ checkNotNull(left, "expected non-null left");
+ checkNotNull(right, "expected non-null right");
+ checkArgument(leftLength >= 0, "expected non-negative leftLength");
+ checkArgument(rightLength >= 0, "expected non-negative rightLength");
- // Walk backwards searching for the insertion point for the item as position i.
- int j;
- for (j = i - 1; j >= 0; j--) {
- UniqueIndexItem y = uniqueIndex[j];
- rightEdit.cellType = LayoutType.FromCode(y.code());
- rightEdit.metaOffset(y.metaOffset());
- rightEdit.valueOffset(y.valueOffset());
-
- int cmp;
- if (scope.get().scopeType() instanceof LayoutTypedMap) {
- cmp = this.compareKeyValueFieldValue(leftEdit.clone(), rightEdit.clone());
- } else {
- int rightBytes = y.size() - (y.valueOffset() - y.metaOffset());
- cmp = this.compareFieldValue(leftEdit.clone(), leftBytes, rightEdit.clone(), rightBytes);
- }
-
- // If there are duplicates then fail.
- if (cmp == 0) {
- return false;
- }
-
- if (cmp > 0) {
- break;
- }
-
- // Swap the jth item to the right to make space for the ith item which is smaller.
- uniqueIndex[j + 1] = uniqueIndex[j];
- }
-
- // Insert the ith item into the sorted array.
- uniqueIndex[j + 1] = x.clone();
+ if (left.cellType().layoutCode().value() < right.cellType().layoutCode().value()) {
+ return -1;
}
- return true;
+ if (left.cellType() != right.cellType()) {
+ return 1;
+ }
+
+ if (leftLength > rightLength) {
+ return 1;
+ }
+
+ if (leftLength < rightLength) {
+ return -1;
+ }
+
+ ByteBuf sliceLeft = this.buffer.slice(left.valueOffset(), leftLength);
+ ByteBuf sliceRight = this.buffer.slice(right.valueOffset(), rightLength);
+
+ return sliceLeft.compareTo(sliceRight);
}
/**
@@ -2263,53 +2341,6 @@ public final class RowBuffer {
return this.compareFieldValue(leftKey, leftKeyLen, rightKey, rightKeyLen);
}
- /**
- * Compares the values of two encoded fields using the hybrid row binary collation.
- *
- * @param left An edit describing the left field.
- * @param leftLength The size of the left field's value in bytes.
- * @param right An edit describing the right field.
- * @param rightLength The size of the right field's value in bytes.
- * @return
- * -
- * -1left less than right.
- *
-
- * 0left and right are equal.
- *
-
- * 1left is greater than right.
- *
- *
- */
- private int compareFieldValue(
- @Nonnull final RowCursor left, final int leftLength, @Nonnull final RowCursor right, final int rightLength) {
-
- checkNotNull(left, "expected non-null left");
- checkNotNull(right, "expected non-null right");
- checkArgument(leftLength >= 0, "expected non-negative leftLength");
- checkArgument(rightLength >= 0, "expected non-negative rightLength");
-
- if (left.cellType().layoutCode().value() < right.cellType().layoutCode().value()) {
- return -1;
- }
-
- if (left.cellType() != right.cellType()) {
- return 1;
- }
-
- if (leftLength > rightLength) {
- return 1;
- }
-
- if (leftLength < rightLength) {
- return -1;
- }
-
- ByteBuf sliceLeft = this.buffer.slice(left.valueOffset(), leftLength);
- ByteBuf sliceRight = this.buffer.slice(right.valueOffset(), rightLength);
-
- return sliceLeft.compareTo(sliceRight);
- }
-
/**
* Compute the number of bytes necessary to store the signed integer using the varint encoding.
*
@@ -2424,7 +2455,7 @@ public final class RowBuffer {
return varint.readerIndex() + varint.readableBytes();
}
- Optional optional = edit.layout().tokenizer().findToken(edit.writePath());
+ Optional optional = edit.layout().tokenizer().tryFindToken(edit.writePath());
if (optional.isPresent()) {
StringToken token = optional.get();
@@ -2591,6 +2622,88 @@ public final class RowBuffer {
}
}
+ /**
+ * Sorts a {@code uniqueIndex} list using the hybrid row binary collation
+ *
+ * @param scope The scope to be sorted.
+ * @param edit A edit that points at the scope.
+ * @param uniqueIndex A unique index array structure that identifies the row offsets of each
+ * element in the scope.
+ * @return true if the array was sorted, false if a duplicate was found during sorting.
+ *
+ * Implementation Note:
+ *
This method MUST guarantee that if at least one duplicate exists it will be found.
+ * Insertion Sort is used for this purpose as it guarantees that each value is eventually compared
+ * against its previous item in sorted order. If any two successive items are the same they must be
+ * duplicates.
+ *
+ * Other search algorithms, such as Quick Sort or Merge Sort, may offer fewer comparisons in the
+ * limit but don't necessarily guarantee that duplicates will be discovered. If an alternative
+ * algorithm is used, then an independent duplicate pass MUST be employed.
+ *
+ *
+ * Under the current operational assumptions, the expected cardinality of sets and maps is
+ * expected to be relatively small. If this assumption changes, Insertion Sort may no longer be the
+ * best choice.
+ *
+ */
+ private boolean insertionSort(
+ @Nonnull final RowCursor scope,
+ @Nonnull final RowCursor edit,
+ @Nonnull final List uniqueIndex) {
+
+ checkNotNull(scope, "expected non-null scope");
+ checkNotNull(edit, "expected non-null edit");
+ checkNotNull(uniqueIndex, "expected non-null uniqueIndex");
+
+ RowCursor leftEdit = edit.clone();
+ RowCursor rightEdit = edit.clone();
+
+ for (int i = 1; i < uniqueIndex.size(); i++) {
+
+ UniqueIndexItem x = uniqueIndex.get(i);
+ leftEdit.cellType(LayoutType.fromCode(x.code()));
+ leftEdit.metaOffset(x.metaOffset());
+ leftEdit.valueOffset(x.valueOffset());
+
+ final int leftBytes = x.size() - (x.valueOffset() - x.metaOffset());
+
+ // Walk backwards searching for the insertion point for the item as position i.
+ int j;
+ for (j = i - 1; j >= 0; j--) {
+ UniqueIndexItem y = uniqueIndex.get(j);
+ rightEdit.cellType(LayoutType.fromCode(y.code()));
+ rightEdit.metaOffset(y.metaOffset());
+ rightEdit.valueOffset(y.valueOffset());
+
+ int cmp;
+ if (scope.scopeType() instanceof LayoutTypedMap) {
+ cmp = this.compareKeyValueFieldValue(leftEdit.clone(), rightEdit.clone());
+ } else {
+ int rightBytes = y.size() - (y.valueOffset() - y.metaOffset());
+ cmp = this.compareFieldValue(leftEdit.clone(), leftBytes, rightEdit.clone(), rightBytes);
+ }
+
+ // If there are duplicates then fail.
+ if (cmp == 0) {
+ return false;
+ }
+
+ if (cmp > 0) {
+ break;
+ }
+
+ // Swap the jth item to the right to make space for the ith item which is smaller.
+ uniqueIndex.set(j + 1, uniqueIndex.get(j));
+ }
+
+ // Insert the ith item into the sorted array.
+ uniqueIndex.set(j + 1, x);
+ }
+
+ return true;
+ }
+
private Item read(@Nonnull final Supplier reader, @Nonnull final RowCursor cursor) {
checkNotNull(reader, "expected non-null reader");
@@ -2799,7 +2912,7 @@ public final class RowBuffer {
* Skip over a nested scope
*
* @param edit The sparse scope to search
- * @return The 0-based byte offset immediately following the scope end marker
+ * @return The zero-based byte offset immediately following the scope end marker
*/
private int skipScope(RowCursor edit) {
@@ -2818,8 +2931,8 @@ public final class RowBuffer {
* Compute the size of a sparse (primitive) field
*
* @param type The type of the current sparse field.
- * @param metaOffset The 0-based offset from the beginning of the row where the field begins.
- * @param valueOffset The 0-based offset from the beginning of the row where the field's value begins.
+ * @param metaOffset The zero-based offset from the beginning of the row where the field begins.
+ * @param valueOffset The zero-based offset from the beginning of the row where the field's value begins.
* @return The length (in bytes) of the encoded field including the metadata and the value.
*/
private int sparseComputePrimitiveSize(LayoutType type, int metaOffset, int valueOffset) {
@@ -2890,20 +3003,13 @@ public final class RowBuffer {
case UTF_8:
case BINARY: {
- int sizeLenInBytes;
- final Out sizeLenInBytes = new Out<>();
- int numBytes = (int) this.read7BitEncodedUInt(metaOffset + metaBytes);
- sizeLenInBytes = tempOut_sizeLenInBytes.get();
- return metaBytes + sizeLenInBytes + numBytes;
+ Item item = this.read(this::read7BitEncodedUInt, metaOffset + metaBytes);
+ return metaBytes + item.length() + item.value().intValue();
}
-
case VAR_INT:
case VAR_UINT: {
- int sizeLenInBytes;
- final Out sizeLenInBytes2 = new Out<>();
- this.read7BitEncodedUInt(metaOffset + metaBytes);
- sizeLenInBytes = tempOut_sizeLenInBytes2.get();
- return metaBytes + sizeLenInBytes;
+ Item item = this.read(this::read7BitEncodedUInt, metaOffset + metaBytes);
+ return metaBytes + item.length();
}
default:
throw new IllegalStateException(lenientFormat("Not Implemented: %s", code));
@@ -3128,6 +3234,10 @@ public final class RowBuffer {
throw new IllegalStateException(lenientFormat("Not Implemented: %s", code));
}
+ private void writeFixedString(Utf8String value) {
+ this.buffer.writeBytes(value.content(), value.encodedLength());
+ }
+
private void writeGuid(UUID value) {
GuidCodec.encode(value, this.buffer);
}
@@ -3148,7 +3258,10 @@ public final class RowBuffer {
checkState(edit.valueOffset() == edit.metaOffset() + metaBytes);
}
- private void writeSparsePath(@Nonnull final RowCursor edit, int offset) {
+ private void writeSparsePath(@Nonnull final RowCursor edit, final int offset) {
+
+ checkNotNull(edit, "expected non-null edit");
+ checkArgument(offset >= 0, "expected non-negative offset");
// Some scopes don't encode paths, therefore the cost is always zero
@@ -3158,24 +3271,23 @@ public final class RowBuffer {
return;
}
- StringToken _;
- Out tempOut__ =
- new Out();
- checkState(!edit.layout().tokenizer().TryFindToken(edit.writePath(), tempOut__) || !edit.writePathToken().isNull());
- _ = tempOut__;
+ final StringTokenizer tokenizer = edit.layout().tokenizer();
+ final Optional writePathToken = tokenizer.tryFindToken(edit.writePath());
+
+ checkState(!(writePathToken.isPresent() && edit.writePathToken().isNull()));
+
if (!edit.writePathToken().isNull()) {
- edit.writePathToken().varint().CopyTo(this.buffer.Slice(offset));
- edit.pathToken(edit.intValue().writePathToken.Id);
+ this.write(this.buffer::writeBytes, offset, edit.writePathToken().varint());
+ edit.pathToken((int) edit.writePathToken().id());
edit.pathOffset(offset);
} else {
- // TODO: It would be better if we could avoid allocating here when the path is UTF16.
- Utf8Span span = edit.writePath().ToUtf8String();
- edit.pathToken = edit.layout().getTokenizer().getCount() + span.Length;
- //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java:
- //ORIGINAL LINE: int sizeLenInBytes = this.Write7BitEncodedUInt(offset, (ulong)edit.pathToken);
- int sizeLenInBytes = this.write7BitEncodedUInt(offset, edit.longValue().pathToken);
- edit.pathOffset = offset + sizeLenInBytes;
- span.Span.CopyTo(this.buffer.Slice(offset + sizeLenInBytes));
+ // TODO: It would be better if we could avoid allocating here when the path is UTF16
+ Utf8String writePath = edit.writePath().toUtf8();
+ checkState(writePath != null);
+ edit.pathToken(tokenizer.count() + writePath.encodedLength());
+ Item item = this.write(this::write7BitEncodedUInt, offset, (long) edit.pathToken());
+ edit.pathOffset(offset + item.length());
+ this.write(this::writeFixedString, edit.pathOffset(), writePath);
}
}
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java
index 1cb4894..851b65a 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java
@@ -52,7 +52,7 @@ public final class RowCursor implements Cloneable {
final SchemaId schemaId = row.readSchemaId(1);
final Layout layout = row.resolver().resolve(schemaId);
- final int sparseSegmentOffset = row.ComputeVariableValueOffset(layout, HybridRowHeader.BYTES, layout.numVariable());
+ final int sparseSegmentOffset = row.computeVariableValueOffset(layout, HybridRowHeader.BYTES, layout.numVariable());
return new RowCursor()
.layout(layout)
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java
index 64aa1f7..fb225f1 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java
@@ -120,7 +120,7 @@ public final class RowCursors {
if (childScope.scopeType().isSizedScope()) {
edit.endOffset(childScope.metaOffset());
} else {
- edit.endOffset(childScope.metaOffset() + (LayoutCode.SIZE / Byte.SIZE)); // move past end of scope marker
+ edit.endOffset(childScope.metaOffset() + LayoutCode.BYTES); // move past end of scope marker
}
}
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java
index 0aedd4a..f444e88 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java
@@ -386,7 +386,7 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope =
new Out();
- this.row.writeSparseObject(tempRef_cursor, scopeType, UpdateOptions.Upsert, tempOut_nestedScope);
+ this.row.writeSparseObject(tempRef_cursor, scopeType, UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope.get();
this.cursor = tempRef_cursor.argValue;
break;
@@ -398,7 +398,7 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope2 =
new Out();
- this.row.WriteSparseArray(tempRef_cursor2, scopeType, UpdateOptions.Upsert, tempOut_nestedScope2);
+ this.row.writeSparseArray(tempRef_cursor2, scopeType, UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope2.get();
this.cursor = tempRef_cursor2.argValue;
break;
@@ -424,7 +424,7 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope4 =
new Out();
- this.row.WriteSparseTuple(tempRef_cursor4, scopeType, typeArg.typeArgs().clone(),
+ this.row.writeSparseTuple(tempRef_cursor4, scopeType, typeArg.typeArgs().clone(),
UpdateOptions.Upsert, tempOut_nestedScope4);
nestedScope = tempOut_nestedScope4.get();
this.cursor = tempRef_cursor4.argValue;
@@ -438,8 +438,8 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope5 =
new Out();
- this.row.WriteTypedTuple(tempRef_cursor5, scopeType, typeArg.typeArgs().clone(),
- UpdateOptions.Upsert, tempOut_nestedScope5);
+ this.row.writeTypedTuple(tempRef_cursor5, scopeType, typeArg.typeArgs().clone(),
+ UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope5.get();
this.cursor = tempRef_cursor5.argValue;
@@ -452,8 +452,8 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope6 =
new Out();
- this.row.WriteTypedTuple(tempRef_cursor6, scopeType, typeArg.typeArgs().clone(),
- UpdateOptions.Upsert, tempOut_nestedScope6);
+ this.row.writeTypedTuple(tempRef_cursor6, scopeType, typeArg.typeArgs().clone(),
+ UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope6.get();
this.cursor = tempRef_cursor6.argValue;
@@ -466,8 +466,8 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope7 =
new Out();
- this.row.WriteTypedTuple(tempRef_cursor7, scopeType, typeArg.typeArgs().clone(),
- UpdateOptions.Upsert, tempOut_nestedScope7);
+ this.row.writeTypedTuple(tempRef_cursor7, scopeType, typeArg.typeArgs().clone(),
+ UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope7.get();
this.cursor = tempRef_cursor7.argValue;
@@ -481,7 +481,7 @@ public final class RowWriter {
Out tempOut_nestedScope8 =
new Out();
this.row.writeNullable(tempRef_cursor8, scopeType, typeArg.typeArgs().clone(),
- UpdateOptions.Upsert, func != null, tempOut_nestedScope8);
+ UpdateOptions.Upsert, func != null);
nestedScope = tempOut_nestedScope8.get();
this.cursor = tempRef_cursor8.argValue;
@@ -508,8 +508,8 @@ public final class RowWriter {
new Reference(this.cursor);
Out tempOut_nestedScope10 =
new Out();
- this.row.WriteTypedSet(tempRef_cursor10, scopeType, typeArg.typeArgs().clone(),
- UpdateOptions.Upsert, tempOut_nestedScope10);
+ this.row.writeTypedSet(tempRef_cursor10, scopeType, typeArg.typeArgs().clone(),
+ UpdateOptions.Upsert);
nestedScope = tempOut_nestedScope10.get();
this.cursor = tempRef_cursor10.argValue;
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java
index ee2ab85..c06e4ec 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java
@@ -9,12 +9,18 @@ import com.azure.data.cosmos.serialization.hybridrow.SchemaId;
import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace;
import com.azure.data.cosmos.serialization.hybridrow.schemas.Schema;
import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind;
+import com.google.common.collect.ImmutableList;
import javax.annotation.Nonnull;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Optional;
+import java.util.stream.Stream;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -42,15 +48,22 @@ public final class Layout {
private final SchemaId schemaId;
private final int size;
private final StringTokenizer tokenizer;
- private final LayoutColumn[] topColumns;
+ private final ImmutableList topColumns;
+ @SuppressWarnings("UnstableApiUsage")
public Layout(
- @Nonnull final String name, @Nonnull final SchemaId schemaId, final int numBitmaskBytes,
- final int minRequiredSize, @Nonnull final ArrayList columns
- ) {
- checkNotNull(name);
- checkNotNull(schemaId);
- checkNotNull(columns);
+ @Nonnull final String name,
+ @Nonnull final SchemaId schemaId,
+ final int numBitmaskBytes,
+ final int minRequiredSize,
+ @Nonnull final ArrayList columns) {
+
+ checkNotNull(name, "expected non-null name");
+ checkNotNull(schemaId, "expected non-null schemaId");
+ checkNotNull(columns, "expected non-null columns");
+
+ checkArgument(numBitmaskBytes >= 0, "expected non-negative numBitmaskBytes, not %s", numBitmaskBytes);
+ checkArgument(minRequiredSize >= 0, "expected non-negative minRequiredSize", minRequiredSize);
this.name = name;
this.schemaId = schemaId;
@@ -60,7 +73,7 @@ public final class Layout {
this.pathMap = new HashMap<>(columns.size());
this.pathStringMap = new HashMap<>(columns.size());
- final ArrayList top = new ArrayList<>(columns.size());
+ ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(columns.size());
int numFixed = 0;
int numVariable = 0;
@@ -77,13 +90,13 @@ public final class Layout {
}
if (column.parent() == null) {
- top.add(column);
+ builder.add(column);
}
}
this.numFixed = numFixed;
this.numVariable = numVariable;
- this.topColumns = top.toArray(new LayoutColumn[0]);
+ this.topColumns = builder.build();
}
/**
@@ -119,10 +132,12 @@ public final class Layout {
}
/**
- * The set of top level columns defined in the layout (in left-to-right order).
+ * Top level columns defined by the current {@link Layout} in left-to-right order
+ *
+ * @return Top level columns defined by the current {@link Layout} in left-to-right order
*/
- public ReadOnlySpan columns() {
- return this.topColumns.AsSpan();
+ public List columns() {
+ return this.topColumns;
}
/**
@@ -186,18 +201,18 @@ public final class Layout {
StringBuilder sb = new StringBuilder();
sb.append("Layout:\n");
- sb.append(String.format("\tCount: %1$s\n", this.topColumns.length));
+ sb.append(String.format("\tCount: %1$s\n", this.topColumns.size()));
sb.append(String.format("\tFixedSize: %1$s\n", this.size()));
for (LayoutColumn column : this.topColumns) {
if (column.type().isFixed()) {
if (column.type().isBoolean()) {
- sb.append(String.format("\t%1$s: %2$s @ %3$s:%4$s:%5$s\n", column.fullPath(), column.type().name(), column.getOffset(), column.getNullBit(), column.getBooleanBit()));
+ sb.append(String.format("\t%1$s: %2$s @ %3$s:%4$s:%5$s\n", column.fullPath(), column.type().name(), column.offset(), column.nullBit(), column.booleanBit()));
} else {
- sb.append(String.format("\t%1$s: %2$s @ %3$s\n", column.fullPath(), column.type().name(), column.getOffset()));
+ sb.append(String.format("\t%1$s: %2$s @ %3$s\n", column.fullPath(), column.type().name(), column.offset()));
}
} else {
- sb.append(String.format("\t%1$s: %2$s[%4$s] @ %3$s\n", column.fullPath(), column.type().name(), column.getOffset(), column.getSize()));
+ sb.append(String.format("\t%1$s: %2$s[%4$s] @ %3$s\n", column.fullPath(), column.type().name(), column.offset(), column.size()));
}
}
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java
index 5211426..2bfb850 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java
@@ -45,7 +45,7 @@ public final class LayoutArray extends LayoutIndexedScope {
return result;
}
- b.WriteSparseArray(edit, this, options, value);
+ b.writeSparseArray(edit, this, options);
return Result.SUCCESS;
}
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java
index 79f584c..d0be5fe 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java
@@ -117,7 +117,7 @@ public final class LayoutBinary extends LayoutType implements ILayoutSpa
return Result.NOT_FOUND;
}
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
value.setAndGet(b.get().readVariableBinary(varOffset));
return Result.SUCCESS;
@@ -255,7 +255,7 @@ public final class LayoutBinary extends LayoutType implements ILayoutSpa
}
boolean exists = b.get().readBit(scope.get().start(), col.getNullBit().clone());
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
int shift;
Out tempOut_shift = new Out();
@@ -283,7 +283,7 @@ public final class LayoutBinary extends LayoutType implements ILayoutSpa
}
boolean exists = b.get().readBit(scope.get().start(), col.getNullBit().clone());
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
int shift;
Out tempOut_shift = new Out();
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java
index d2c71f0..bf0c37b 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java
@@ -80,7 +80,7 @@ public final class LayoutNullable extends LayoutIndexedScope {
return result;
}
- b.get().writeNullable(edit, this, typeArgs.clone(), options, hasValue, value.clone());
+ b.get().writeNullable(edit, this, typeArgs.clone(), options, hasValue);
return Result.SUCCESS;
}
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java
index 72dbf1d..8650ed4 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java
@@ -148,7 +148,7 @@ public abstract class LayoutType implements ILayoutType {
boolean exists = b.readBit(scope.start(), column.nullBit());
if (exists) {
- int varOffset = b.ComputeVariableValueOffset(scope.layout(), scope.start(), column.offset());
+ int varOffset = b.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
b.deleteVariable(varOffset, this.isVarint());
b.unsetBit(scope.start(), column.nullBit());
}
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java
index 5762a6b..85d236c 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java
@@ -92,7 +92,7 @@ public final class LayoutUtf8 extends LayoutType implements ILayoutUtf8S
return Result.NOT_FOUND;
}
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
value.setAndGet(b.get().readVariableString(varOffset));
return Result.SUCCESS;
@@ -149,7 +149,7 @@ public final class LayoutUtf8 extends LayoutType implements ILayoutUtf8S
return result;
}
- b.get().WriteSparseString(edit, value, options);
+ b.get().writeSparseString(edit, value, options);
return Result.SUCCESS;
}
@@ -173,7 +173,7 @@ public final class LayoutUtf8 extends LayoutType implements ILayoutUtf8S
}
boolean exists = b.get().readBit(scope.get().start(), col.getNullBit().clone());
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
int shift;
Out tempOut_shift = new Out();
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java
index 0962176..97cb5ae 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java
@@ -98,7 +98,7 @@ public final class LayoutVarInt extends LayoutType {
}
boolean exists = b.get().readBit(scope.get().start(), col.getNullBit().clone());
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
int shift;
Out tempOut_shift = new Out();
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java
index 6856294..de8eb4c 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java
@@ -115,7 +115,7 @@ public final class LayoutVarUInt extends LayoutType {
}
boolean exists = b.get().readBit(scope.get().start(), col.getNullBit().clone());
- int varOffset = b.get().ComputeVariableValueOffset(scope.get().layout(), scope.get().start(),
+ int varOffset = b.get().computeVariableValueOffset(scope.get().layout(), scope.get().start(),
col.getOffset());
int shift;
Out tempOut_shift = new Out();
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java
index 3a91d2a..f5326a9 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java
+++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java
@@ -54,7 +54,7 @@ public final class StringTokenizer {
* @param path The string to look up.
* @return {@code true} if successful, {@code false} otherwise.
*/
- public Optional findToken(UtfAnyString path) {
+ public Optional tryFindToken(UtfAnyString path) {
if (path.isNull()) {
return Optional.empty();