diff --git a/src/main/java/com/amazon/ion/impl/bin/IonRawBinaryWriter.java b/src/main/java/com/amazon/ion/impl/bin/IonRawBinaryWriter.java index 7fe56a71c..489f12e46 100644 --- a/src/main/java/com/amazon/ion/impl/bin/IonRawBinaryWriter.java +++ b/src/main/java/com/amazon/ion/impl/bin/IonRawBinaryWriter.java @@ -614,22 +614,18 @@ private ContainerInfo popContainer() // The number of bytes we need to shift by is determined by the writer's preallocation mode. final int numberOfBytesToShiftBy = preallocationMode.numberOfLengthBytes(); - // `length` is the encoded length of the container/wrapper we're stepping out of. It does not - // include any header bytes. In this `if` branch, we've confirmed that `length` is <= 0xD, - // so this downcast from `long` to `int` is safe. - final int lengthOfSliceToShift = (int) length; - // Shift the container/wrapper body backwards in the buffer. Because this only happens when // `lengthOfSliceToShift` is 13 or fewer bytes, this will usually be a very fast memcpy. // It's slightly more work if the slice we're shifting happens to straddle two memory blocks // inside the buffer. - buffer.shiftBytesLeft(lengthOfSliceToShift, numberOfBytesToShiftBy); + // `length` is the encoded length of the container/wrapper we're stepping out of. It does not + // include any header bytes. In this `if` branch, we've confirmed that `length` is <= 0xD, + // so this downcast from `long` to `int` is safe. + buffer.shiftBytesLeft((int)length, numberOfBytesToShiftBy); // Overwrite the lower nibble of the original type descriptor byte with the body's encoded length. final long typeDescriptorPosition = positionOfFirstLengthByte - 1; - final long type = (buffer.getUInt8At(typeDescriptorPosition) & 0xF0) | length; - buffer.writeUInt8At(typeDescriptorPosition, type); - + buffer.writeLowerNibbleAt(typeDescriptorPosition, length); // We've reclaimed some number of bytes; adjust the container length as appropriate. length -= numberOfBytesToShiftBy; } diff --git a/src/main/java/com/amazon/ion/impl/bin/WriteBuffer.java b/src/main/java/com/amazon/ion/impl/bin/WriteBuffer.java index fba4c60d4..7e67af00b 100644 --- a/src/main/java/com/amazon/ion/impl/bin/WriteBuffer.java +++ b/src/main/java/com/amazon/ion/impl/bin/WriteBuffer.java @@ -104,17 +104,6 @@ public long position() return (((long) index) * allocator.getBlockSize()) + current.limit; } - private static final int OCTET_MASK = 0xFF; - - /** Returns the octet at the logical position given. */ - public int getUInt8At(final long position) - { - final int index = index(position); - final int offset = offset(position); - final Block block = blocks.get(index); - return block.data[offset] & OCTET_MASK; - } - /** Writes a single octet to the buffer, expanding if necessary. */ public void writeByte(final byte octet) { @@ -1266,12 +1255,24 @@ public void writeUInt8At(final long position, final long value) { final int index = index(position); final int offset = offset(position); - // XXX we'll never overrun a block unless we're given a position past our block array final Block block = blocks.get(index); block.data[offset] = (byte) value; } + /** + * Overwrite the lower nibble of the specified type descriptor byte with the length information. + * @param position represents the position of the byte that will be overwritten. + * @param value represents the length value of the container. + */ + public void writeLowerNibbleAt(final long position, final long value) { + final int index = index(position); + final int offset = offset(position); + final Block block = blocks.get(index); + long bitValue = block.data[offset]; + block.data[offset] = (byte) (bitValue & 0xF0 | value) ; + } + /** Get the length of FlexInt for the provided value. */ public static int flexIntLength(final long value) { int numMagnitudeBitsRequired;