diff --git a/bson/src/main/org/bson/BsonBinaryWriter.java b/bson/src/main/org/bson/BsonBinaryWriter.java index e6255ea847..dd0a3e1ffa 100644 --- a/bson/src/main/org/bson/BsonBinaryWriter.java +++ b/bson/src/main/org/bson/BsonBinaryWriter.java @@ -37,8 +37,16 @@ public class BsonBinaryWriter extends AbstractBsonWriter { private final BsonOutput bsonOutput; private final Stack maxDocumentSizeStack = new Stack<>(); + private static final int ARRAY_INDEXES_CACHE_SIZE = 256; + private static final String[] ARRAY_INDEXES_CACHE = new String[ARRAY_INDEXES_CACHE_SIZE]; private Mark mark; + static { + for (int i = 0; i < ARRAY_INDEXES_CACHE_SIZE; i++) { + ARRAY_INDEXES_CACHE[i] = Integer.toString(i); + } + } + /** * Construct an instance. * @@ -397,7 +405,12 @@ public void reset() { private void writeCurrentName() { if (getContext().getContextType() == BsonContextType.ARRAY) { - bsonOutput.writeCString(Integer.toString(getContext().index++)); + int index = getContext().index++; + if (index >= ARRAY_INDEXES_CACHE_SIZE) { + bsonOutput.writeCString(Integer.toString(index)); + } else { + bsonOutput.writeCString(ARRAY_INDEXES_CACHE[index]); + } } else { bsonOutput.writeCString(getName()); } diff --git a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java index 8e0f7c23c2..84f2aeca65 100644 --- a/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java +++ b/bson/src/test/unit/org/bson/BsonBinaryWriterTest.java @@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.List; import static java.util.Arrays.asList; @@ -49,7 +50,7 @@ public class BsonBinaryWriterTest { @BeforeEach public void setup() { buffer = new BasicOutputBuffer(); - writer = new BsonBinaryWriter(new BsonWriterSettings(100), new BsonBinaryWriterSettings(1024), buffer); + writer = new BsonBinaryWriter(new BsonWriterSettings(100), new BsonBinaryWriterSettings(12904), buffer); } @AfterEach @@ -61,7 +62,7 @@ public void tearDown() { public void shouldThrowWhenMaxDocumentSizeIsExceeded() { try { writer.writeStartDocument(); - writer.writeBinaryData("b", new BsonBinary(new byte[1024])); + writer.writeBinaryData("b", new BsonBinary(new byte[12904])); writer.writeEndDocument(); fail(); } catch (BsonMaximumSizeExceededException e) { @@ -197,16 +198,39 @@ public void testWriteArray() { } @Test - public void testWriteArrayElements() { + public void testWriteArrayElements() throws IOException { + ByteArrayOutputStream expectedOutput = new ByteArrayOutputStream(); + expectedOutput.write(new byte[]{ + 88, 11, 0, 0, //document length + 4, // array type + 97, 49, 0, // "a1" name + null terminator + 79, 11, 0, 0}); // array length + writer.writeStartDocument(); writer.writeStartArray("a1"); - writer.writeBoolean(true); - writer.writeBoolean(false); + int arrayIndex = 0; + while (arrayIndex < 500) { + writer.writeBoolean(true); + + expectedOutput.write(BsonType.BOOLEAN.getValue()); + expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); + expectedOutput.write(0); // null terminator + expectedOutput.write(1); // boolean value + + writer.writeBoolean(false); + + expectedOutput.write(BsonType.BOOLEAN.getValue()); + expectedOutput.write(Integer.toString(arrayIndex++).getBytes(StandardCharsets.UTF_8)); + expectedOutput.write(0); // null terminator + expectedOutput.write(0); // boolean value + } writer.writeEndArray(); + expectedOutput.write(0); // end of array writer.writeEndDocument(); - byte[] expectedValues = {22, 0, 0, 0, 4, 97, 49, 0, 13, 0, 0, 0, 8, 48, 0, 1, 8, 49, 0, 0, 0, 0}; - assertArrayEquals(expectedValues, buffer.toByteArray()); + expectedOutput.write(0); // end of a document + + assertArrayEquals(expectedOutput.toByteArray(), buffer.toByteArray()); } @Test